指针变量和引用变量的区别

指针变量和引用变量的区别

技术背景

在C++编程中,指针和引用是两个重要的概念,它们都用于间接访问对象。指针是一个变量,存储的是另一个对象的内存地址;而引用可以看作是对象的别名,它必须在初始化时绑定到一个对象,并且之后不能再重新绑定。理解它们之间的区别对于编写高效、安全的C++代码至关重要。

实现步骤

1. 可重赋值性

指针可以重新赋值,指向不同的对象;而引用在初始化后不能重新绑定,必须在初始化时就绑定到一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
// 指针可重赋值
int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;
*p = 10;
// 此时 x 仍为 5,y 变为 10

// 引用必须初始化且不能重绑定
// int &q; // 错误,引用必须初始化
int &r = x;

2. 自身身份

指针变量有自己独立的内存地址,可以使用&运算符获取,也可以使用sizeof运算符测量其占用的空间。而对引用使用这些运算符,返回的是引用所绑定对象的值,引用自身的地址和大小是不可见的。

1
2
3
4
5
6
7
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;

assert(p == p2); // &x == &r
assert(&p != &p2);

3. 多级嵌套

可以创建指向指针的指针,但不能创建指向引用的指针。

1
2
int **pp; // 合法,指向指针的指针
// int &*pr; // 非法,指向引用的指针

4. 数组使用

可以创建指针数组,但不能创建引用数组。

1
2
int *ap[]; // 合法,指针数组
// int &ar[]; // 非法,引用数组

5. 空值处理

指针可以被赋值为nullptr,而引用必须绑定到一个已存在的对象。虽然可以尝试将引用绑定到nullptr,但这是未定义行为。

1
2
3
4
5
// 指针可赋值为 nullptr
int *p = nullptr;

// 引用绑定到 nullptr 是未定义行为
// int &r = *static_cast<int *>(nullptr);

6. 迭代操作

指针是连续迭代器,可以使用++操作符指向下一个元素,也可以使用+ n操作符指向第n+1个元素。

1
2
3
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
p++; // 指向 arr[1]

7. 成员访问

指针需要使用->操作符来访问所指向对象的成员,而引用可以直接使用.操作符。

1
2
3
4
5
6
7
8
9
10
11
class MyClass {
public:
int value;
};

MyClass obj;
MyClass *p = &obj;
p->value = 10;

MyClass &r = obj;
r.value = 20;

8. 临时对象绑定

常量引用和右值引用可以绑定到临时对象,而指针不能直接绑定到临时对象。

1
2
const int &x = int(12); // 合法
// int *y = &int(12); // 非法,不能取临时对象的地址

核心代码

以下是一个综合示例,展示了指针和引用在函数参数传递中的不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

// 使用指针作为参数
void swapWithPointer(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}

// 使用引用作为参数
void swapWithReference(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}

int main() {
int x = 5, y = 10;

// 使用指针交换
swapWithPointer(&x, &y);
std::cout << "After swap with pointer: x = " << x << ", y = " << y << std::endl;

x = 5;
y = 10;

// 使用引用交换
swapWithReference(x, y);
std::cout << "After swap with reference: x = " << x << ", y = " << y << std::endl;

return 0;
}

最佳实践

  • 使用引用的场景:当需要避免对象的复制,提高性能,并且不需要空值语义时,优先使用引用。例如,函数参数传递和返回值。
  • 使用指针的场景:当需要空值语义,或者需要进行指针算术运算时,使用指针。例如,动态内存分配和数据结构的实现。

常见问题

1. 引用是否占用内存?

引用是否占用内存是未指定的,取决于编译器的实现。在大多数情况下,引用可能会被实现为指针,但在语义上,引用是对象的别名,不占用额外的内存。

2. 能否有空引用?

C++ 标准中没有空引用的概念。引用必须在初始化时绑定到一个已存在的对象。如果尝试将引用绑定到nullptr,会导致未定义行为。

3. 指针和引用哪个更安全?

在大多数情况下,引用比指针更安全,因为引用必须在初始化时绑定到一个对象,并且不能重新绑定,避免了悬空引用的问题。而指针需要手动管理,容易出现空指针和悬空指针的问题。但在某些情况下,指针的灵活性也是必要的。


指针变量和引用变量的区别
https://119291.xyz/posts/2025-05-09.differences-between-pointer-and-reference-variables/
作者
ww
发布于
2025年5月9日
许可协议