指针就是指向变量的地址,而引用是变量的别名,通过指针或引用都可以修改变量的值,但两者的使用上会有一些差异,比如:
- 引用在定义的时候必须初始化,且只能指向一个变量,后续不能指向其它变量。而指针在定义的时候可以不初始化,且后续可以修改指向为其它地址;
- 引用的大小是所指向变量的大小,而指针的大小则是固定的,32位系统为4字节,64位系统位8字节;
- 引用比指针更安全,因为引用在定义的时候必须初始化,所以不可能为空,而指针可能为空,所以指针使用前必须判空;
- 引用可以直接使用,而指针需要用*;
还是通过代码来理解,定义了几个函数:
void print(int *pn)
{
cout<<"print(int *pn): pn\t"<<pn<<endl;
cout<<"print(int *pn): &pn\t"<<&pn<<endl;
cout<<"print(int *pn): *pn\t"<<*pn<<endl;
*pn = 12;
}
void print(int &pn)
{
cout<<"print(int &pn): pn\t"<<pn<<endl;
cout<<"print(int &pn): &pn\t"<<&pn<<endl;
pn = 13;
}
void print2(int *&pn)
{
cout<<"print2(int *&pn): *pn\t"<<*pn<<endl;
cout<<"print2(int *&pn): &pn\t"<<&pn<<endl;
cout<<"print2(int *&pn): pn\t"<<pn<<endl;
*pn = 14;
}
int n = 10;
int *pn = &n;
cout<<"例子1: 传指针 ---------->"<<endl;
print(pn);
cout<<__func__<<"\tpn\t"<<pn<<endl;
cout<<__func__<<"\t&pn\t"<<&pn<<endl;
cout<<__func__<<"\t*pn\t"<<*pn<<endl;
cout<<"例子2: 传引用 ---------->"<<endl;
print(*pn);
cout<<__func__<<"\tpn\t"<<pn<<endl;
cout<<__func__<<"\t&pn\t"<<&pn<<endl;
cout<<__func__<<"\t*pn\t"<<*pn<<endl;
cout<<"例子3: 传指针引用 ---------->"<<endl;
print2(pn);
cout<<__func__<<"\tpn\t"<<pn<<endl;
cout<<__func__<<"\t&pn\t"<<&pn<<endl;
cout<<__func__<<"\t*pn\t"<<*pn<<endl;
输出结果:
例子1: 传指针 ---------->
print(int *pn): pn 0x7ffeed4af9b4
print(int *pn): &pn 0x7ffeed4af828
print(int *pn): *pn 10
main pn 0x7ffeed4af9b4
main &pn 0x7ffeed4af9a8
main *pn 12
例子2: 传引用 ---------->
print(int &pn): pn 12
print(int &pn): &pn 0x7ffeed4af9b4
main pn 0x7ffeed4af9b4
main &pn 0x7ffeed4af9a8
main *pn 13
例子3: 传指针引用 ---------->
print2(int *&pn): *pn 13
print2(int *&pn): &pn 0x7ffeed4af9a8
print2(int *&pn): pn 0x7ffeed4af9b4
main pn 0x7ffeed4af9b4
main &pn 0x7ffeed4af9a8
main *pn 14
在例子1中,print(int *pn)函数和main函数输出的&pn是不一样的,一个是0x7ffee9fa9838,一个是0x7ffee9fa99a8,因为print(int *pn)函数是传值,没错,传值,只是这个值是“指针”,它会生成一个指针的副本,因此print(int *pn)函数和main函数输出的&pn会不一样。
注意⚠️,还有一个容易忽视的错误,看代码:
void testPtr(int *pi)
{
pi = new int;
cout<<__func__<<"\t"<<pi<<endl;
}
int main() {
int *pi = new int(100);
cout<<"pi -> "<<pi<<endl;
testPtr(pi);
cout<<"pi -> "<<pi<<endl;
}
运行结果:
pi -> 0x7fa03b402ae0
testPtr 0x7fa03b402af0
pi -> 0x7fa03b402ae0
可能有人会认为在testPtr能够修改pi的值,但正如上面所说的,指针是传值,作为testPtr的参数时,是生成了一个指针的副本,因此在testPtr函数内,修改的是指针副本的值,而不是main函数中定义的pi的值。
还有一个关于引用的例子,看代码:
int &max(int &a, int &b)
{
return a > b ? a : b;
}
int n1 = 11, n2 = 12;
cout<<++max(n1,n2)<<"\t"<<n1<<"\t"<<n2<<endl;
程序输出:
13 11 13
max函数返回的是n2的引用,因此++max(n1,n2)会修改n2的值⚠️。