目录
一、什么是引用做返回值?
在C++中,函数不仅可以返回普通值,也可以返回引用。
普通返回值写法:
cpp
int func() {
int a = 10;
return a;
}
引用返回值写法:
cpp
int& func() {
static int a = 10;
return a;
}
这里函数返回类型是:
cpp
int&
表示函数返回的是一个整型变量的引用,也就是返回这个变量的别名。
二、传值返回
普通函数返回值一般是传值返回。
例如:
cpp
#include <iostream>
using namespace std;
int func() {
int a = 10;
return a;
}
int main() {
int ret = func();
cout << ret << endl;
return 0;
}
运行结果:
cpp
10
这种方式是安全的。
因为函数返回时,会把a的值拷贝一份返回给外面。
但缺点是:
如果返回值是大对象,拷贝成本会比较高。
三、引用返回
引用返回不会重新拷贝一份数据,而是返回原对象的别名。
例如:
cpp
#include <iostream>
using namespace std;
int& func() {
static int a = 10;
return a;
}
int main() {
int& ret = func();
cout << ret << endl;
ret = 20;
cout << func() << endl;
return 0;
}
运行结果:
cpp
10
20
这里func()返回的是static int a的引用。
所以:
cpp
int& ret = func();
相当于ret成了a的别名。
后面修改ret,其实就是修改a。
四、为什么不能返回普通变局部量的引用?
下面这种写法时错误的:
cpp
int& func() {
int a = 10;
return a;
}
原因是a是普通局部变量。
普通局部变量由于存放在函数栈帧中,函数调用结束后,a的空间就被释放了。
这时候在返回a的引用,相当于返回了一个已经失效的变量。
这种情况叫悬空引用。
错误示例:
cpp
#include <iostream>
using namespace std;
int& func()
{
int a = 10;
return a;
}
int main()
{
int& ret = func();
cout << ret << endl;
return 0;
}
这段代码虽然可能编译通过,但是结果是不靠谱的。
所以要记住:
不要反返回普通局部变量的引用。
五、为什么static变量可以引用返回?
static修饰局部变量生命周期不是函数的调用期间,而是整个程序的运行期间。
例如:
cpp
int& func() {
static int a = 10;
return a;
}
虽然a写在函数内部,但是不会随着函数结束而销毁。
所以函数结束后,a仍然存在。
因此返回a的引用是可以的。
简单理解:
| 变量类型 | 函数结束后是否还存在 | 能不能返回引用 |
|---|---|---|
| 普通局部变量 | 不存在 | 不建议 |
| static 局部变量 | 仍然存在 | 可以 |
| 全局变量 | 仍然存在 | 可以 |
六、引用返回优点以及注意事项
引用返回的最大优点:
减少拷贝,提高效率。
引用返回时,必须注意对象的生命周期。
核心规则:
返回引用时,返回对象必须是在函数结束后仍然存在的。
可以返回:
cpp
static局部变量
全局变量
已经存在的对象成员
不要返回:
cpp
普通局部变量
临时变量
函数内部创建但很快销毁的对象
七、小结
本篇主要学习了引用做返回值。
需要记住:
- 函数返回类型是可以引用的;
- 引用返回的是对象的别名;
- 引用返回可以减少拷贝,提高效率;
- 普通局部变量不能引用返回;
- static局部变量可以引用返回;
- 返回引用时,必须保证返回对象在函数结束后仍然存在;
- 引用返回使用不当会产生悬空引用。
引用做返回值时C++中比较重要的知识点,后面学习类和对象、运算符重载、STL容器时都会经常用到。