引用
先声明:引用的本质是const指针,以下内容只帮助理解.
我的面前放了一个包裹,名字叫a。
int a = 0;//值为0的int型变量(一个对象)
我大喊一声:“xx处有个包裹a!” 这句完整的话语,称为b。
int &b = a; //引用b绑定给对象a
通过我说的的这句话,你可以找到包裹a的位置,获取里面的资源。
你可以这样理解:
- 这句话只有在明确表示包裹位置时才有意义(引用必须被初始化)
- 已经说出口的话不能收回修改,除非我再说另一句话告诉你新的情况(引用只能绑定一次,不可再绑定给另一个对象)
- 至于我刚才说的话,你无法真正触碰到它,我也没法告诉你那句话去哪里了(不能定义引用的引用)
指针
然后我又放了一块指示牌,名字叫p1,写上一句话:“XX处有个包裹a”
int *p1 = &a;//&是取地址符,所以&a就是那句话
也许做上面这些事的过程中我累了,我会选择分两段进行,先休息一会,再把内容补上,也没有问题。
int *p1;//定义指针变量p1
p1 = &a;//a的地址赋值给p1
注意:
- 指示牌是专门用来告诉人们东西所处位置的(指针存放对象的地址)
- 我可以先放牌子,再写内容(指针不用初始化),或写上“这是块假的指示牌”(生成空指针),但诸如此类的牌子同样使人迷惑(不能用于访问对象)
- 一块牌子可能不够看的,我可以再放一块牌子p2,把上一块牌子p1的内容照抄过去, 就像这样,如此一来我相当于有了两块功能一样的牌子——p1和p2,它们虽然摆放的位置不同,但都指向同一个包裹。
int *p2 = p1;//p2的值就p1的值
- 由于指示牌和包裹一样是实实在在的物体(指针本身是对象),所以我可以再放一块牌子,上面告诉你第一块牌子的位置(可以用一个指针的地址给另一个指针赋值),于是我可以通过名为p3的指示牌顺藤摸瓜找到p1,最后一样找到了包裹a
int **p3 = &p1;
std::cout << **p3 ;
- 对了,之前说过,我没法告诉你【我说的话】去哪了,同样的,用牌子写字的方式也没法告诉你它去哪了(不能定义指向引用的指针)
总结
如果以上的瞎扯不是很让人理解,那么可以参照下面的代码总结:
#include<iostream>
using namespace std;
int main()
{
/*
int *x * 定义指针类型
int &x & 定义引用类型
*x * 解引用符
&x & 取地址符
直接使用x,得到x对象本身
如果x的值是地址,x前面加上*后,得到那个地址的变量的值
x前面加&,得到x的地址
*/
int a = 1;//变量
cout << "value of a: " << a << endl;//1
cout << "address of a: " << &a <<endl;//0x61fe04
int &y = a;//引用(本质是常量指针,相当于int *const y = &a;)
//这里其实不是y的值,而是a的值(相当于*y)
cout << y << endl;//1
//这里不是y的地址,是a的地址(相当于&(*y))
cout << &y << endl;//0x61fe04
int *p1 = &a;//指针
//p1的值就是a的地址
cout << p1 << endl;//0x61fe04
//p1值所指向的目标,就是a
cout << *p1 << endl;//1
//p1的地址
cout << &p1 << endl;//0x61fdf8
//把p1的值,也就是a的地址赋值给p2,此时 p1 == p2 && *p1 == *p2
int *p2 = p1;
//p2的值就是a的地址
cout << p2 << endl;//0x61fe04
//p2的值等于a的地址,所以*p2是a的值
cout << *p2 << endl;//1
cout << (p1 == p2 && *p1 == *p2) << endl;//1
//把p1的地址赋值给p3,p3是个指向指针的指针
int **p3 = &p1;
//p3的值就是p1的地址
cout << p3 <<endl;//0x61fdf8
//p3值所指向的目标是p1,所以*p3相当于p1
cout << *p3 << endl;//0x61fe04
//而p1的值是a的地址,所以*p3等于a的地址
//所以在*p3基础上再解一次引用就是a本身了
cout << **p3 << endl;//1
return 0;
}
对于*解引用符号,这里只有输出的用法,赋值也是一样的,对*p1赋值就是对p1所指的对象赋值