引入

问题代码

#include <iostream>

//const T&可接取右值表达式
const std::string foo(const std::string& s) {
return s;
}

int main() {
//"Hello world!"被构造为string,纯右值,在本句全表达式中有效
auto& ref = foo("Hello world!");

//有的编译器可以输出,有的不行,属于UB,悬垂引用
std::cout << ref << std::endl;
}

“Hello world!”的构建

auto& ref = foo("Hello world!");
/*
* 调用std::string转换构造函数,将字面量字符串转换为std::string
* =>auto& ref = foo(std::string("Hello world!"));
*/

结论

在函数调用中绑定到函数形参的临时量,存在到含这次函数调用的全表达式结尾为止:如果函数返回一个生命长于全表达式的引用,那么它会成为悬垂引用。

——引用初始化 - cppreference.com

临时对象的生存周期存在于全表达式。

表达式结束,生命周期结束。

易混淆的点

return 语句中绑定到函数返回值的临时量不会被延续:它在返回表达式的末尾立即销毁。这种 return 语句始终返回悬垂引用。

——引用初始化 - cppreference.com

这种描述指的是以下情况

const std::string& foo() {
return std::string("temporary string");
}