面试题答案
一键面试常引用的生命周期管理
- 常规情况:通常情况下,引用会延长对象的生命周期。当一个引用绑定到一个临时对象时,临时对象的生命周期会延长到引用的生命周期结束。
- 本题情况:然而,在
const std::string& getString()
返回临时std::string
对象的常引用时,这是一种不安全的做法。因为函数返回后,临时对象会被销毁,此时引用就变成了悬空引用(dangling reference)。尽管常引用在语法上看似能延长临时对象的生命周期,但这里返回的临时对象在函数结束时就会被销毁,并不会因为引用而延长。
潜在问题
- 未定义行为:当使用这个悬空引用去操作对象时,会导致未定义行为。例如,访问对象的成员函数或数据成员时,程序可能崩溃、产生错误的结果或者出现其他不可预测的行为。
解决方案
- 返回值优化(RVO):直接返回
std::string
对象,让编译器执行返回值优化。这样编译器会优化掉不必要的对象拷贝,直接在调用者的栈上构造对象。
std::string getString() {
return std::string("example");
}
- 使用
std::move
(如果需要避免不必要拷贝):如果函数内部已经有一个std::string
对象,并且希望避免不必要的拷贝,可以使用std::move
。
std::string getString() {
std::string str("example");
return std::move(str);
}
- 在调用处创建对象并传入函数:可以将接收结果的对象作为参数传入函数,让函数填充这个对象。
void getString(std::string& result) {
result = "example";
}
然后调用:
std::string s;
getString(s);