我要理解 C++ 引用
2018-06-30 本文已影响43人
1999c1b720cd
背景
实际项目中涉及到对 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 「对象的副本」进行操作,那么需要自己拷贝一份
- 虽然传递「大对象」可以用指针解决,但是「小对象」就没必要了,然而引用更灵活,不管大小对象都适用,兼容性好
内部原理
引用就是对象的别名- 编译器是如何处理引用的?
优缺点
- 优点是减少函数调用时参数拷贝的性能开销
最佳实践
- 不要返回函数局部对象的引用,栈上数据会被后续函数修改
- 函数参数尽量使用引用
练习题
- 对比引用和被引用对象的地址,在使用层面理解引用的本质
总结
- 最后得出一句话「引用就是变量的别名,指向同一个内存地址」