指针和引用的区别

发布时间 2023-04-05 09:52:38作者: real010

指针和引用在 C++ 中都用于间接访问变量,但它们有一些区别:

  1. 指针是一个变量,它保存了另一个变量的内存地址,引用是另一个变量的别名,与原变量共享内存地址。
  2. 指针可以被重新赋值,指向不同的变量,引用在初始化后不能更改,始终指向同一个变量。
  3. 指针可以为 nullptr,表示不指向任何变量;引用必须绑定到一个变量,不能为 nullptr。
  4. 使用指针需要对其进行解引用以获取或修改其指向的变量的值,引用可以直接使用,无需解引用。

下面的示例展示了指针和引用的区别:

#include <iostream>

int main() {
    int a = 10;
    int b = 20;

    // 指针
    int *p = &a;
    std::cout << "Pointer value: " << *p << std::endl; // 输出:Pointer value: 10

    p = &b;
    std::cout << "Pointer value: " << *p << std::endl; // 输出:Pointer value: 20

    // 引用
    int &r = a;
    std::cout << "Reference value: " << r << std::endl; // 输出:Reference value: 10

    // r = &b; // 错误:引用不能被重新绑定
    int &r2 = b;
    r = r2; // 将 b 的值赋给 a,r 仍然引用 a
    std::cout << "Reference value: " << r << std::endl; // 输出:Reference value: 20

    return 0;
}

从汇编底层角度来解释 C++ 中引用的实现机制的话,引用是别名这是C++语法规定的语义,那么到底引用在汇编层面和指针有什么区别呢?其实没区别。引用会被 C++ 编译器当做const指针来进行操作。

简单总结

  • 引用只是C++语法糖,可以看作编译器自动完成取地址、解引用的常量指针
  • 引用区别于指针的特性都是编译器约束完成的,一旦编译成汇编就和指针一样
  • 由于引用只是指针包装了下,所以也存在风险,比如如下代码:
int *a = new int;
int &b = *a;
delete a;
b = 12;    // 对已经释放的内存解引用
  • 引用由编译器保证初始化,使用起来较为方便(如不用检查空指针等)
  • 引用没有顶层const即int & const,因为引用本身就不可变,所以在加顶层const也没有意义; 但是可以有底层const即 const int&,这表示引用所引用的对象本身是常量
  • 指针既有顶层const(int * const--指针本身不可变),也有底层const(const int *--指针所指向的对象不可变)
  • 有指针引用--是引用,绑定到指针, 但是没有引用指针--这很显然,因为很多时候指针存在的意义就是间接改变对象的值,但是引用本身的值我们上面说过了是所引用对象的地址,但是引用不能更改所引用的对象,也就当然不能有引用指针了。
  • 指针和引用的自增和自减含义不同,指针是指针运算, 而引用是代表所指向的对象执行++或--