引用
我们常用的引用都是左值引用,而什么是引用呢,所为的引用其实就是给对象起了另一个名字。要注意的是引用不是对象,同时,引用必须要进行初始化。
看下代码吧:
int ival = 1024;
int &refval = ival; // 用 & 来表示refval是ival的引用
int &refval2; // 这里会报错,因为引用必须初始化
为什么必须进行初始化呢?因为在定义引用的时候,程序把引用和他的初始值绑定在一起,记住,绑定不是拷贝,也就是说如果你对利用引用修改值,那么被引用的对象的值也会发生变化。并且,引用一旦绑定之后就不可更改,这也就是为什么引用必须初始化的原因。
//用代码举个例子吧
int ival = 1024;
int &refval = ival;
refval = 3;
cout<<ival<<endl;//这里的输出结果是三,说明ival的值也被改变了
引用的定义
允许在一条语句中定义多个引用,当然,每个引用的标志符都必须以&开头:
int i = 1, i2 = 2;//定义两个普通的int类型
int &j = i, k = i2;//其中j是对I的引用,k是普通的int变量
int &m = i, &n = m;//m是对I的引用,而n是对i的引用的引用,其实就是这个意思,给小李取了一个外号叫
//李子,然后又给李子取了个外号叫木子
&j = i2;//error:Expression is not assignable
指针
指针是指向另外一种类型的复合类型,用来存放对象的地址。和引用相似,指针也实现的对其他对象的简介访问。然而指针和引用相比有着许多的不同之处。首先,指针本身就是一个对象,由声明符*和变量名组成如:*p。所以指针可以不初始化(但这样做会出现问题,后面再讲,不过编译器是不会报错的),因此也允许对齐进行赋值和拷贝。第二,指针所指向的对象可以随时改变。
int i = 1;
int *p = &i; // 这里的&是去地址符。不是引用的意思,表示p存放i的地址
int *p1,*p2; // 编译器不会报错,因为指针可以不初始化
p1 = p; // p1和p同时指向i
形如p2,并没有被初始化,这首p2 就会变成一个野指针,p2的默认值是随机,我们也不知道p2指向的是内存中的哪个位置。野指针的危害就还请百度吧,这里就不多说了。
利用指针访问对象
如果指针指向了一个对象,可以使用解引用符* 来访问该对象。
可能会有疑惑,如同引用& 和地址&,指针*和解引用*,其实代表不是同样的东西,只是写法相同罢了(我就是这么理解的,具体代表什么意思看情况而定,应该还是好分辨的)
比如我们要输出i的值,可以这样:
cout<<*p<<endl;
int &k = *p;//这里的*也是解引用的意思
cout<<k<<endl;//这样也是可以的
通过解引用符*来获取p所存的地址的对象的值。
空指针
空指针不指向任何对象,在试图使用一个指针之前代码可以首先检查它是否为空。以下列出几个生成空指针的方法:
int *p = nullptr;//c++11的一种新方法,就是空的意思
int *p1 = 0;//直接初始化为字面常量0
int *p2 = NULL;//其实和上面等于0时一样的
其他指针操作
int ival = 11;
int *p1 = &ival;
int *p2 = 0;
if(p1)
{
cout<<"p1 is true"<<endl;
}
if(p2)
{
cout<<"p2 is true"<<endl;
}
//输出结果
//p1 is true
原因就是,如果指针的值是0,条件取false,否则,全部为true。这里说一下 ,如果是nullptr的话,直接理解空和非空就好了。
void* 指针
void* 是一种特殊的指针类型,用于存放任何对象的地址。但是,我们永远无法理解该地址的对象是什么类型的,这也就导致我们无法直接操作void*指针所指的对象,换句话说就是问无法通过void*来访问内存空间中所存储的对象。
int obj = 2;
double * p2 = 0;
void* p3 = &obj;
p3 = p2;
指向指针的指针
先说一下变量吧,变量的定义包括一个基本的数据类型和一组声明符(比如 int *p , int是数据类型,*是声明符中的修饰符,p是名字)。并且声明符中的修饰符的个数并没有限制。如下:
int ival = 22;
int *p = &ival; //p指向ival
int **pp = &p; //pp 指向一个int形的指针
int ***ppp = &pp; //ppp 指向一个指向int型的指针的指针
如果想输出ival的话也有很多方法:
cout<<*p<<endl;
cout<<**pp<<endl;
cout<<***ppp<<endl;
//上面的*全部都是解引用的意思
指向指针的引用
上面也说过了,引用本身并不是一个对象,而只是一个别名(外号),因此不能定义指向引用的指针,但指针是一个对象,所以存在对指针的引用。是不是有点绕,所以看代码可能会好理解点。
int ival = 11;
int *p = &ival;//这句话其实可以拆成两句话。int *p, p = &ival;
int **pp = &p;
int *&r = p; //从右向左读吧,其中&代表r是一个引用,*代表其是对指针的引用
int **&rr = pp;//一样的道理 **代表其事对指针的指针的引用
*r = 22;
cout<<ival<<endl;//输出结果为 22
**rr = 33;
cout<<ival<<endl;//输出结果为 33
总结:
以上内容许多是参考c++primer 这本书的,也别说抄袭了,因为这篇博客更多的是一种学习笔记吧,全部手打的。博主本人也水平有限,大概加了一点自己的尝试和想法,希望共同进步吧。