目录
引用:
在C++中,引用是一种为已存在变量创建别名的机制,它允许通过不同的名称访问同一块内存空间的数据。

上述图对应的引用代码:
cpp
int a=1;
int &b=a;
先初始化定义一个变量a,编译器会为变量a开辟一个存储空间并存储值。然后又对变量a进行了一个引用将变量b绑到变量a的内存地址,不会额外占用内存空间,也就是变量b是变量a的别名,变量a和变量b的地址都是一样的,对同一块内存空间进行管理。变量b也能访问变量a中的值并且也能进行修改。
访问变量a的存储空间中的值需要先知道变量a的地址。我们可以把变量a的存储空间看成一个房间,而变量a的地址就是这个房间的门牌号,变量b对变量a进行一个引用,就相当于把变量b也当成变量a的房间号,然后通过变量b也能够找到该房间。变量a和变量b都这间房间的门牌号,无论谁对房间里面的值进行修改,变量a和变量b的值都会发生变化。
注意:
引用前必须进行初始化:引用在创建时必须被初始化,它必须指向某个已存在的对象。
一旦绑定之后,不可改变:引用一旦被初始化后,它将一直保持与其初始对象的绑定,不能改变为另一个对象的引用。
没有空引用:引用必须指向某个对象,不能存在空引用。
左值引用和右值引用:
左值引用:
表示持久化对象,具有明确内存地址(可&
取址),可以被多次赋值,可出现在赋值符号左侧或右侧。可以被多次赋值。
右值引用:
表示临时对象或字面量,无持久地址(不可&
取址),仅能出现在赋值符号右侧。主要用于是在函数参数和返回值中,以实现更高效的资源管理和更灵活的代码编写方式。
指针:
指针是存储内存地址的变量,通过地址间接访问数据。其值为另一个变量的内存位置直接地址,而不是数据本身。引用本身不是一个对象,不能定义只想引用的指针。

cpp
int a = 10;
int *b = &a;
初始化定义变量a,编译器会为其开辟一个空间并存储值。"int *b = &a"将变量a的地址进行赋值给变量b,因为变量b也是一个变量,所以编译器也会其开辟一个存储空间,将变量a的地址存储到变量b的内存空间中。
指针的地址也可以用另一个指针进行存储。

cpp
int a = 10;
int *b= &a;
int **c = &b;
使用一个指针c将指针b的地址存储到其存储空间中。如果想要通过其存储的地址进行访问到变量a具体的值,那么就可以进行解引用操作来进行访问。
cpp
std::cout<<"a的值"<<a<<std::endl;
std::cout<<"通过指针b访问"<<*b<<std::endl;
std::cout<<"通过指针c访问"<<**c<<std::endl;

指针c通过一次解引用"*c"得到的就是指针b也就是变量a的地址,因为指针c中存储的是变量b的地址,c就代表变量b的地址,那么对c进行一次解引用就会得到指针b中存储的内容。再对指针b进行一个解引用"*b"那么就相当于对指针c进行了两次解引用操作"**c"就是对指针b中存储的内容(变量a的地址)进行一次解引用,那么就会得到变量a中的值。
指针的一个运算:
数组的数组名就是一个指向数组的首元素的指针,如果定义一个指针存储数组首元素的地址进行一个自增的话,因为数组是一块连续的内存空间,根据数组存储的数据类型占用的字节大小,来进行一个首元素地址,也就是起始地址来进行偏移,得到下一个元素的内存地址。
注意:数组名是一个常量指针,不可以修改指向,对数组名进行修改是非法的。可以通过数组名+i,来进行一个数组中元素的偏移地址。

cpp
int arr[10] = {0};
int *p = arr;
std::cout<<p<<std::endl;
p++;
std::cout<<p<<std::endl;
可以用上述方式进行一个验证。
指针与引用的区别:
指针可以不用进行初始化,引用必须进行初始化。
指针是一个变量,编译器会为其分配存储空间,而引用不是一个对象,不会为其分配存储空间。
指针可以进行多级引用,而引用不可以多级引用。
指针在其生命周期内可以修改指向的对象,而引用一旦绑定对象之后,则不可以进行修改。
对指针进行计算大小:sizeof(指针)的大小与指向的数据类型无关,在32位系统中为4字节,在64为系统中占8字节,而引用不同,因为引用本身不占独立的存储空间,sizeof(引用)的大小是其绑定对象的大小。
指针可以为空,而引用不能为空,必须绑定对象。