C++ Pointer & Reference
C++中指针和引用的区别是一个经典且重要的面试问题。让我详细解释它们的区别:
1. 定义和初始化
指针
1 2 3 4
| int x = 10; int* ptr; ptr = &x; int* ptr2 = &x;
|
引用
1 2 3
| int x = 10; int& ref = x;
|
2. 重新赋值
指针
1 2 3 4 5 6
| int x = 10, y = 20; int* ptr = &x; cout << *ptr << endl;
ptr = &y; cout << *ptr << endl;
|
引用
1 2 3 4 5 6 7
| int x = 10, y = 20; int& ref = x; cout << ref << endl;
ref = y; cout << ref << endl; cout << x << endl;
|
3. 空值和有效性
指针
1 2 3 4 5 6 7
| int* ptr = nullptr; if (ptr != nullptr) { cout << *ptr << endl; }
int* ptr2;
|
引用
1 2 3 4 5
|
int x = 10; int& ref = x; cout << ref << endl;
|
4. 内存占用
指针
1 2 3 4 5
| int x = 10; int* ptr = &x;
cout << sizeof(ptr) << endl; cout << sizeof(x) << endl;
|
引用
1 2 3 4 5 6
| int x = 10; int& ref = x;
cout << sizeof(ref) << endl; cout << sizeof(x) << endl;
|
5. 算术运算
指针
1 2 3 4 5 6 7 8 9
| int arr[] = {1, 2, 3, 4, 5}; int* ptr = arr;
cout << *ptr << endl; cout << *(ptr + 1) << endl; cout << *(ptr + 2) << endl;
ptr++; cout << *ptr << endl;
|
引用
1 2 3 4 5 6 7 8
| int arr[] = {1, 2, 3, 4, 5}; int& ref = arr[0];
cout << ref << endl;
|
6. 作为函数参数
指针参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void func1(int* ptr) { if (ptr != nullptr) { *ptr = 100; } }
void func2(int* ptr) { ptr = new int(200); }
int main() { int x = 10; int* p = &x; func1(p); func2(p); func1(nullptr); }
|
引用参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void func1(int& ref) { ref = 100; }
int main() { int x = 10; func1(x); }
|
7. 返回值使用
返回指针
1 2 3 4 5 6 7 8
| int* createInt() { return new int(42); }
int* dangerousFunc() { int x = 10; return &x; }
|
返回引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int& getElement(vector<int>& vec, int index) { return vec[index]; }
int& dangerousFunc() { int x = 10; return x; }
int main() { vector<int> vec = {1, 2, 3}; getElement(vec, 1) = 100; cout << vec[1] << endl; }
|
8. 总结对比表
特性 |
指针 |
引用 |
初始化 |
可选 |
必须 |
重新赋值 |
可以 |
不可以 |
空值 |
可以 |
不可以 |
算术运算 |
支持 |
不支持 |
内存占用 |
占用额外空间 |
通常不占用 |
语法复杂度 |
需要 * 和 & |
简洁 |
安全性 |
需要检查 |
相对安全 |
多级间接 |
支持(指针的指针) |
不支持 |
使用建议
- 优先使用引用:当你需要别名时,引用更安全、语法更简洁
- 使用指针:当需要可选性(可为空)、重新赋值、或指针算术时
- 函数参数:引用用于必须传递有效对象的情况,指针用于可选参数
- 动态内存:必须使用指针(配合智能指针更好)