C++中指针与引用的区别
指针用操作符”*”和”->”,引用使用操作符”&”。指针与引用都是让你间接引用其他对象。
指针是一个存储地址的变量,这个地址指向内存的一个存储单元。引用跟原来的变量实质上是同一个东西,只是原变量的一个别名。
函数形参为指针时,传递进来的是实参指针值的copy,即形参是实参的一个副本,实参指针本身的地址值不会变。因此函数对形参的任何操作都是作为局部变量进行,不会影响实参的值。而引用传递过程中,形参是实参变量的地址。函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。因此对形参的修改其实是对实参的修改。对指针的引用(*&p,也等价于*(&p))也是引用的一种,其实就是引用的变量变成了指针。
举例:
#include<iostream>
using namespace std;
void swap1(int *p1, int *p2) { // 指针变量作形参,形参形参复制了实参的值,指针交换实际是形参copy的交换,实参指针不变
int *temp = p1;
p1 = p2;
p2 = temp;
cout << "swap1中交换后函数中形参指针变量p1和p2的结果:" << endl;
cout << p1 << " " << p2 << endl;
}
void swap2(int &a, int &b) { // 引用变量做形参,函数中交换的是两个变量的值,两个变量的地址均不变
int temp = a;
a = b;
b = temp;
cout << "swap2中交换后函数中形参引用变量a和b的结果:" << endl;
cout << a << " " << b << endl;
}
void swap3(int *&p1, int *&p2) { // 引用指针变量作形参,形参存放的是实参指针的地址,函数交换了两个实参指针的值,也就是交换了变量的地址
int *temp = p1;
p1 = p2;
p2 = temp;
cout << "swap3中交换后函数中形参引用指针变量p1和p2的结果:" << endl;
cout << p1 << " " << p2 << endl;
}
int main() {
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
cout << "初始情况下全局变量p1、a、p2、b的值如下:" << endl;
cout << p1 << " " << a << " " << p2 << " " << b << endl;
swap1(p1, p2);
cout << "swap1交换完成后全局变量p1、a、p2、b的结果:" << endl;
cout << p1 << " " << a << " " << p2 << " " << b << endl;
// 注意swap2交换后变量a和b的地址没变,是变量的值(地址的内容)改变了
swap2(a, b);
cout << "swap2交换完成后全局变量p1、a、p2、b的结果:" << endl;
cout << p1 << " " << a << " " << p2 << " " << b << endl;
//注意swap3交换后交换的是p1和p2指针的值
swap3(p1, p2);
cout << "swap3交换完成后全局变量p1、a、p2、b的结果:" << endl;
cout << p1 << " " << a << " " << p2 << " " << b << endl;
return 0;
}
任何情况下都不能使用指向空值的引用。一个引用必须指向某个对象。如果一个变量在某些时候可能不指向任何对象,那么应当把变量声明为指针,因为这样你可以赋空值给该变量。
引用必须指向一个对象,因此,在C++中引用必须被初始化。另外,由于引用必须指向一个对象,因此在使用引用之前不需要测试它的合法性,而指针则应该总是被测试合法性。
举例:
string &rs; // 错误,引用必须被初始化
string &rs = "xyzzy"; // 正确
string *ps; // 未初始化的指针,合法但危险
指针与引用的另一个重要不同是指针可以被重新赋值以指向另一个不同的对象。而引用则总是指向在初始化时被指定的对象,以后不能改变。
举例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "Nancy";
string s2 = "Clancy";
string s3 = "Alice";
string &rs = s1; // rs引用s1
string *ps = &s1; // ps指向s1
cout << s1 << " " << s2 << endl;
cout << rs << " " << *ps << endl;
rs = s2; // rs仍旧引用s1,但是s2的值赋给了s1,s1的值现在是"Clancy"
ps = &s2; // ps现在指向s2,s1没有改变
cout << s1 << " " << s2 << endl;
cout << rs << " " << *ps << endl;
s2 = s3; // s3的值赋给s2
cout << s1 << " " << s2 << endl;
cout << rs << " " << *ps << endl;
}
何时使用指针,何时使用引用
以下情况下你应该使用指针:
- 变量存在不指向任何对象的可能时;
- 需要改变变量指向的对象时。
以下情况你应该使用引用:
- 变量总是指向一个对象并且一旦指向一个对象后就不会再改变,那么你应该使用引用。