引用,指针,数组名
1.引用和指针
- | 引用 | 指针 |
---|---|---|
定义上 | 定义时必须初始化且后续不能更改。引用只有一级 | 可以先定义,后面用到了再初始化。后续可以指向其他变量,指针可以有多级 |
值上 | 引用必须绑定到一个具体的、已经存在的对象上。(因此不能用退化的临时变量来初始化,见后文引用数组) | 指针没有太多限制,会导致安全问题 |
空状态 | 引用必须引用一个具体的对象,不能是空 | 指针可以是空 |
操作上 | 引用就像普通变量,不需要特殊语法 | 必须使用解地址符来访问其数据 |
引用的底层实现是指针(VS2022):因此引用需要用左值进行初始化
int &p=30;是不可以的
int a = 10;
00007FF7A2571AAD mov dword ptr [a],0Ah
int* p = &a;
00007FF7A2571AB4 lea rax,[a]
00007FF7A2571AB8 mov qword ptr [p],rax
//下面引用的实现,在编译器用指针进行实现
int& b = a;
00007FF7A2571ABC lea rax,[a]
00007FF7A2571AC0 mov qword ptr [b],rax
*p = 20;
00007FF7A2571AC4 mov rax,qword ptr [p]
00007FF7A2571AC8 mov dword ptr [rax],14h
b = 30;
00007FF7A2571ACE mov rax,qword ptr [b]
00007FF7A2571AD2 mov dword ptr [rax],1Eh
2.数组
2.1 arr和&arr
arr | &arr | |
---|---|---|
值 | 第一个元素的地址 | 第一个元素的地址 |
类型上 | 在大多数情况下(除去sizeof、&)会被隐式退化成指向第一个元素的指针。 | 是指向整个数组的指针。 类型为int(*)[5], |
操作上 | arr+1会移动到下一个元素的位置(即向前移动int大小) | &arr+1会移动到整个数组以外的下一个位置(即移动sizeof(int)*5的大小)。因为&arr是指向整个数组的指针。 |
sizeof函数 | 不会退化为指向第一个元素,因此返回整个数组大小 | 返回指针大小 |
&操作符 | 不会退化。返回的是指向整个数组的指针 | - |
int arr[5]={1,2,3,4,5}
cout << arr << endl; //000000F1824FFBA8
cout << typeid(arr).name() << endl; //int [5]
cout << sizeof(arr) << endl; //20
cout << &arr << endl; //000000F1824FFBA8
cout << typeid(&arr).name() << endl; //int (* __ptr64)[5]
cout << sizeof(&arr) << endl; //8
2.2 引用数组
int arr[5] = {1,2,3,4,5};
int* &p = arr; // 这行是错误的
int(&p2)[5] = arr; // 这行是正确的
解释错误:
声明要求 p 必须初始化为绑定到一个已存在的 int* 类型的指针上。然而,在示例中,arr 是一个数组类型,不是一个指针类型,尽管它在表达式中会退化为指向其第一个元素的指针(即 int*)。但这种退化产生的是一个临时的指针值,不是一个可以持久绑定的指针变量。
因此,尝试将 arr 直接赋值给 int* &p 是非法的,因为这相当于试图让引用绑定到一个临时产生的右值上。
正确的使用int *&p:
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // ptr 是一个指针,指向 arr 的第一个元素
int* &p = ptr; // p 现在是对 ptr 的引用
3.左值引用和右值引用
思考
int a=10;
int*p = &a;
const int *&q=p;
问代码可不可以?
int a=10;
int*p = &a;
const int *&q=p;//假设可以
const int b=99;
q=&b;
*p = 33;
如果const int *&q=p;
执行成功。那么q
和p
就是等价的了,执行完q=&b;
以后,q(p)
指向了一个const
变量,那么我后续可以通过p(int *)
来修改一个const
变量。
因此这种做法是错误的。
对于指针的引用如何判断是否可以?
方法:把引用改成指针
const int *&q=p;
--> const int **&*q=*p
上文中,我们知道int**
不能直接赋值给const int **
因此,这种方法是错误的