如果我在C ++ 11中保持对函数的非引用返回值的常量引用,那么堆栈中的引用点在哪里?这样做是否安全?
string foo() {
std::string foo_ret = "foo string";
return foo_ret;
}
int main() {
const std::string& a = foo();
}
答案 0 :(得分:4)
您的代码是非法的;非const左值引用可能不绑定到rvalues。这背后并没有真正的好原因,它只是C ++历史上很早就引入的一种语言规则。
MSVC过去(可能仍然如此)允许这种绑定,我无法评论MSVC如何实现它。
您可以绑定到其他引用类型:
std::string const &a = foo(); // (1)
std::string&& b = foo(); // (2)
在情况(2)中,b
直接绑定到返回值对象,返回值对象的生命周期延长到匹配b
的生命周期。注意:此处不会发生“移动”操作,它只是绑定引用。
在情况(1)中,从概念上讲,从返回值初始化类型const std::string
的临时值,并且该临时值的生命周期延长到匹配a
的生存期。实际上,此副本将为elided。您的代码就像引用直接绑定到返回值一样。
一般来说,您应该使用值语义。 std::string c = foo();
是最安全的选择。由于复制省略,它的效率并不比参考选项低。
引用选项的主要危险在于,如果更改了函数以返回引用,则a
或b
可能会成为悬空引用。
答案 1 :(得分:0)
不这样做是不安全的,这是一个错误,不会编译。
您可能正在寻找R值引用:http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
答案 2 :(得分:0)
在我看来,这样做是合法的。
当您从函数返回string
时,它会返回Rvalue
或临时对象。您无法使用普通Lvalue
引用来获取Rvalue
,但您可以使用const Lvalue
引用来获取。当您使用const Lvalue
引用时,临时对象的生命周期将扩展为与引用相同。
至于参考指向内存的位置,我猜它可能因实现而异。但重要的是临时对象不再是“临时对象”,尽管你无法改变它。