我要理解 C++ 引用

背景

实际项目中涉及到对 C++ 引用的使用,这里记录个人对其的理解,并把它加入到个人「专业」知识结构

是什么

  • 在 C++ 编程语言中的引用是一种「复合数据类型」,是在基本类型的基础上衍生出来的类型
  • 从 C 语言中的「指针」衍生出来的比指针「安全」但没有指针强大的一种数据类型
  • 在实现上,引用可以作为「已存在」的「对象」的「新名字」。举个例子,如图所示,假设 obj 变量在内存中 0x08E4100 地址处,我们定义一个 reference 引用 obj 对象,则 reference 变量的地址也是 0x08E4100

为什么

从使用的角度来分析,C++ 语言使用引用是为了解决函数调用时参数拷贝导致的性能问题

怎么用

方法参数

引用作为方法参数可以实现传出「方法结果」的目的

void square(int x, int& result) 
{
    result = x * x;
}
  • 上面 square 方法调用后,从 result 变量可以拿到 x 的平方信息
  • 调用方不用进行不必要的取地址操作,更「节省时间」

方法返回值

int& preinc(int& x) 
{
    return ++x;  // "return x++;" 这样写会出错?临时对象?
}

preinc(y) = 5; // 等同于 ++y, y = 5;
  • 方法返回引用可以作为「左值」被赋值
  • 不要返回「局部」对象的引用,因为调用结束后栈上局部对象的「内存」会被后续函数调用破坏
  • 因为引用就是「原对象」的「别名」,故把它当做原对象使用,左值和右值都一样使用

优化方法调用时参数拷贝开销

void f_slow(BigObject x) { /* ... */ }  
void f_fast(const BigObject& x) { /* ... */ }

BigObject y;

f_slow(y); // 很慢,因为要拷贝 y 对象到 x 对象
f_fast(y); // 很快,因为直接访问只读变量 y 的地址
  • 通常函数调用时使用 const T & 可以减少「对象拷贝」时间开销
  • 如果 f_fast 内部需要对 y 「对象的副本」进行操作,那么需要自己拷贝一份
  • 虽然传递「大对象」可以用指针解决,但是「小对象」就没必要了,然而引用更灵活,不管大小对象都适用,兼容性好

内部原理

我要理解 C++ 引用_第1张图片
引用就是对象的别名
  • 编译器是如何处理引用的?

优缺点

  • 优点是减少函数调用时参数拷贝的性能开销

最佳实践

  • 不要返回函数局部对象的引用,栈上数据会被后续函数修改
  • 函数参数尽量使用引用

练习题

  • 对比引用和被引用对象的地址,在使用层面理解引用的本质

总结

  • 最后得出一句话「引用就是变量的别名,指向同一个内存地址」

参考

【1】C++ 引用 https://en.wikipedia.org/wiki/Reference_(C++)

你可能感兴趣的:(我要理解 C++ 引用)