C++中指针和引用的区别?

66 阅读5分钟

C++中指针和引用的区别?

公众号:阿Q技术站

1. 指针(Pointer)

指针是一个变量,用于存储另一个变量的内存地址。通过指针,你可以访问并修改指向的变量内容。指针是 C++ 中非常强大的功能,但也容易出错,需要小心管理内存,避免出现如空指针、野指针等问题。

指针的特点
  • 指针可以为空:指针可以指向 nullptr,表示指针不指向任何有效内存地址。
  • 指针可以改变指向:指针可以指向不同的内存地址。
  • 使用解引用:通过解引用操作符 * 来访问指针所指向的值。
  • 需要手动管理内存:指针通常与动态内存分配 (new / delete) 一起使用。
指针的基本语法
int* ptr;   // 声明一个指向 int 的指针
int a = 10;
ptr = &a;   // 将指针 ptr 指向 a 的地址
示例代码
#include <iostream>
using namespace std;
​
int main() {
    int a = 10;
    int* ptr = &a;  // ptr 是指向 a 的指针
​
    cout << "Value of a: " << a << endl;        // 输出 a 的值
    cout << "Value via ptr: " << *ptr << endl;  // 通过指针访问 a 的值
​
    *ptr = 20;  // 通过指针修改 a 的值
​
    cout << "Value of a after modification: " << a << endl;  // 输出修改后的 a 的值
​
    return 0;
}

输出结果:

Value of a: 10
Value via ptr: 10
Value of a after modification: 20
解释
  • ptr = &a;ptr 指向 a 的地址。
  • 通过解引用 *ptr 可以访问指针所指向的内容。
  • 使用 *ptr = 20; 直接通过指针修改了 a 的值。

2. 引用(Reference)

引用是一个已存在变量的别名。引用在声明时必须被初始化,且在整个生命周期中不能再改变指向的对象。引用让代码更简洁,因为它在语法上就像是原始变量的别名,而无需显式的解引用。

引用的特点
  • 引用必须初始化:引用在声明时必须绑定到一个变量,并且一旦绑定就不能改变。
  • 引用不可为空:引用必须绑定到一个有效的对象,不能为空。
  • 没有解引用操作符:引用在语法上像原始变量,可以直接操作。
  • 引用不能改变指向:一旦引用绑定到某个变量,它不能再绑定到其他变量。
引用的基本语法
int a = 10;
int& ref = a;  // ref 是 a 的引用
示例代码
#include <iostream>
using namespace std;
​
int main() {
    int a = 10;
    int& ref = a;  // ref 是 a 的引用
​
    cout << "Value of a: " << a << endl;    // 输出 a 的值
    cout << "Value via ref: " << ref << endl;  // 通过引用访问 a 的值
​
    ref = 20;  // 通过引用修改 a 的值
​
    cout << "Value of a after modification: " << a << endl;  // 输出修改后的 a 的值
​
    return 0;
}

输出结果:

Value of a: 10
Value via ref: 10
Value of a after modification: 20
解释
  • ref = a; 使得 ref 成为 a 的引用,之后就可以像访问 a 一样使用 ref
  • 通过引用修改 a 的值,不需要解引用操作符。

3. 指针与引用的区别

特性指针(Pointer)引用(Reference)
定义指针是一个变量,存储另一个变量的内存地址。引用是另一个变量的别名,直接与原变量绑定。
初始化可以在声明后初始化,可以为 nullptr必须在声明时初始化,且不能为 nullptr
是否可改变指向可以改变指针的指向,指向不同的变量。一旦引用绑定到某个变量,不能再改变引用的目标。
是否为空可以为 nullptr,表示不指向任何有效的内存。引用不能为空,必须引用一个有效的对象。
访问方式需要解引用(*)操作符来访问所指向的内容。可以像原始变量一样直接访问,不需要解引用。
内存管理指针与动态内存(new / delete)关系密切,需手动管理内存。引用不涉及动态内存管理,通常不需要考虑内存管理。
是否可用于数组指针可以指向数组或容器元素,支持指针算术运算。引用无法直接进行指针算术运算,不能作为数组的迭代器。
常见用途动态内存分配、函数返回多个值、构建链表等。函数参数传递(尤其是避免大对象拷贝)、返回对象引用。

4. 指针和引用的使用场景

指针
  • 动态内存管理:当你需要在运行时分配和释放内存时,指针是必不可少的。
  • 函数返回动态数据:当你需要返回指向堆中数据的指针时,指针是合适的选择。
  • 指向数组或对象:指针可以用来遍历数组或作为容器中元素的指针。
  • 实现链表等数据结构:指针可以通过指向下一个元素来构建链表、树等数据结构。
引用
  • 函数参数传递:引用用于避免不必要的拷贝,尤其是大对象时。通过引用传递可以直接操作原对象。
  • 返回对象的引用:引用可作为函数返回值类型,返回类成员或容器中的元素引用。
  • 简化代码:引用让代码更简洁,特别是在需要修改传入的变量时,不需要使用指针解引用。