引用基础知识
明确“常量引用”只是对 const的引用 的简称,严格来说 不存在常量引用,因为引用不是一个对象,所以没法让引用本身不变。
引用必须初始化,引用相当于变量的另外一个名字,但引用不是一个对象,没有实际的地址,且引用不能重新绑定在另外一个对象。
指针无须在定义时赋值,指针是一个对象 ,因为引用没有实际的地址,所以不能定义指向引用的指针
int i, &a=i;|
int *p = a;//是错误的,因为a是一个引用,指针不能定义指向引用
一般情况指针和指针指向的对象的类型是匹配的。
void * 一种特殊类型的指针,可以存放任意类型对象的地址,因为这样导致并不知道这个对象是什么类型,所以不能直接操作void*所指的对象,只是一个内存空间,无法访问内存空间中所存对象。
例如:
double i1 = 3.14;
void *p1 = nullptr;
p1 = &i1;
cout << *p1 << endl; //错误的,因为void * 不能直接操作对象,这里*p解引用符是指向操作对象,所以错误
指针引用的作用
只有指针的引用,没有引用的指针 因为引用不是一个对象,
指针引用 *& 可以 替代 二级指针
以下普通 代替 非常量
string s;
const string ss;
string* ps1 = &s;//普通指针
const string* ps = &s;//指向常量的指针绑定在非常量上
//首先是一个sting* 普通指针,然后va0是一个非常量引用
//(va0是一个非常量引用,引用绑定的类型必须严格一致,在这里必须是string*)
string* &va0 = ps1;//正确: ps1类型是string* 与左边严格匹配
//并且ps1非常量,所以自然可以绑定
string* &va0 = &s;//错误: 类型与左边不严格匹配
//且普通引用不能绑定到一个临时变量,因为没有明确对象
string* &va0 = &ss;//错误: 类型与左边不严格匹配 且普通指针不能绑定到常量对象地址,且&ss是一个临时变量,
//普通引用不能绑定到一个临时变量,因为没有明确对象
string* &va0 = ps;//错误: 类型与左边不严格匹配
//首先是一个常量指针,val是一个引用 然后引用绑定在这个常量指针上
//(这样va1是一个指向string的const指针的引用 ,val就有了"常量引用"的特性)
string* const & val = &s;//正确: 常量指针绑定到普通对象地址 尽管&s是一个临时变量
//但va1是一个"常量引用"可以绑定临时变量
string* const & val = ps1;//正确: 普通指针绑定到普通指针
//ps1普通指针对象,va1一个"常量引用"可以绑定它
string* const & val = &ss;//错误: 常量指针绑定到常量对象地址
//
string* const & val = ps;//错误: 常量指针绑定到常量对象
//
//根据编译器报错知道 ,va2是一个普通引用,指针是一个指向常量的指针,指针本身不是常量
//(va2是一个非常量引用,所以类型必须一致,不存在其他转换,类型严格匹配)
const string* & va2 = ps;//正确: 因为ps就是const string*类型与左边严格匹配
//ps本身也不是常量,所以va2非常量引用自然可以绑定
const string* & va2 = ps1;;//错误:因为类型与左边不严格匹配
//尽管指向常量的指针是可以绑定到ps1这个非常量
const string* & va2 = &s;//错误:因为类型与左边不严格匹配
//错误:普通引用不能绑定临时对象&s
const string* & va2 = &ss;//错误:因为类型与左边不严格匹配
//错误:普通引用不能绑定临时对象&ss
//首先是一个指向常量的常量指针,然后va3是一个引用
//(va3是一个指向const string的const指针的引用,va3就有了"常量引用"的特性)
const string* const & va3 = &s; //正确:指向常量的指针决定绑定指针可以是常量也可以是非常量,
//"常量引用"决定可以绑定一个临时变量,常量对象以及非常量对象
const string* const & va3 = &ss; //正确
const string* const & va3 = ps; //正确
const string* const & va3 = ps1; //正确