C++学习2.3_引用,指针
1.引用必须被初始化。
程序将引用和它的初始值绑定在一起,而不是将初始化拷贝给引用,因为无法令引用重新绑定到另一个对象,因此引用必须初始化。
2.引用即别名
引用并不是对象,只是为一个已经存在的对象起的一个别名。
3.引用只能定义在对象上,而不能与某个字面值或某个表达式的计算结果绑定在一起。
int &refVal4 = 10; //错误 ,引用只能定义在对象上
double dval = 3.14;
int &refVal5 = dval; //错误,引用以及初始值类型不同。
引用的类型要与之绑定的对象类型严格匹配。
指针
指针是指向另外一种类型的复合类型,实现了对其他对象的间接访问。与引用的不同点如下:
a.指针本身是一个对象,允许指针赋值和拷贝,可以在指针生命周期先后指向不同的对象。
b.指针无须再定义时赋初值,在块作用域内定义的指针如果没有被初始化,将拥有一个不确定的值。
获取对象的地址
指针若想获取某对象的地址,需要使用取地址符。( & )
指针的类型要和它所指向的对象严格匹配。
int ival = 42;
int *p = &ival; //p存放变量ival的地址,或者说p是指向变量ival的指针。
指针与引用:因为引用不是对象,没有实际地址,因此不能定义指向引用的指针。
指针的值
指针的值(即地址)应属于下列四种状态之一
a.指向一个对象。
b.指向紧邻对象所占空间的下一个位置。
c.空指针,意味着指针没有指向任何对象。[访问无效指针的后果无法预计,野指针的危害!]
d.无效指针。也就是上述情况之外的其它值。
这里写个小程序输出一下指针里面的东西:
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 double dval; 6 double *pd = &dval; 7 8 double *pd2 = pd; 9 10 dval = 3.1; 11 cout<<" dval "<<dval<<endl<<" pd "<<pd<<endl<<"*pd "<<*pd<<endl; 12 return 0; 13 }
其输出结果为:
利用指针来访问对象
如果指针指向了一个对象,则允许使用解引用符( * )来访问该对象。【就像上面代码里所表示的那样】
对指针解引用会得出所指的独享,因此如果给解引用的结果赋值,实际上也就是给指针所指的对象赋值
注意:解引用符仅仅适用于确实指向了某个对象的有效指针。
关键概念:有多重含义的符号,符号的上下文决定了符号的意义。
在之前的代码基础上增加了一些引用指针的一些操作验证:
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 double dval; 6 double *pd = &dval; 7 8 double *pd2 = pd; 9 10 dval = 3.1; 11 cout<<" dval "<<dval<<endl<<" pd "<<pd<<endl<<"*pd "<<*pd<<endl; 12 13 double *pd3; 14 15 pd3 = pd; 16 cout<< *pd3<<endl; 17 18 *pd = 4.1; 19 cout<<"*pd "<<*pd<<" "<<"dval "<<dval<<" "<<endl; 20 21 cout<<"***************************************************"<<endl; 22 23 double &r2 = *pd;//引用,r2引用指针pd,因为指针是一个对象,可以这么搞,其实相当于 &r2 = dval; 24 cout<<"r2 "<<r2; 25 26 return 0; 27 }
其输出为:
空指针
空指针不指向任何对象,生成空指针的方法如下:
int *p1 = nullptr; //等价于int *p1 = 0; int * p2 = 0; //需要include cstdlib Int *p3 = NULL; //等价于int *p3 = 0 ;
上面的几种方法里,第一个nullptr是C++11新标准刚引入的一种方法。
第三个,使用名未NULL的预处理变量来给指针赋值,这个变量在cstdlib中定义,它的值为0;
【在新标准下建议使用第一个】
建议初始化所有的指针,这很重要!
赋值和指针
要搞清一条赋值语句到底是改变了指针的值还是指针所指对象的值,最好的办法就是记住: 赋值永远改变的是等号左侧的对象。
其它指针操作
只要指针拥有一个合法值,就能将他用在条件表达式中,如果指针的值为0,则条件取false;而任何非0指针对应的条件都是true;
void* 指针
void* 是一种特殊的指针类型,可以用于存放任意对象的地址,只是对地址中到底是个什么类型的对象并不了解。
不能直接操作void*指针所指的对象,因为不知道类型。
指向指针的指针
通过指针的个数来区别指针的级别,**表示指向指针的指针,**表示指向指针的指针的指针。
从左至右第一个pointer存放的是pi的地址,第二个pointer存放的是value的地址。所以,*pi就是value的值,pi就是value的地址,ppi是pi的地址,*ppi是value的地址,**ppi就是value的值。
[一次解引用得到的是所指向的指针里存放的东西,也就是value的地址,第二次解引用就是value的值。
指向指针的引用
引用本身不是对象,因此不能定义指向引用的指针,但是指针是对象,所以存在对指针的引用。