在C ++中保持对函数返回值的常量引用

时间:2015-08-11 23:57:32

标签: c++ c++11 reference return-value

如果我在C ++ 11中保持对函数的非引用返回值的常量引用,那么堆栈中的引用点在哪里?这样做是否安全?

string foo() {
  std::string foo_ret = "foo string";
  return foo_ret;
}

int main() {
  const std::string& a = foo();
}

3 个答案:

答案 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();是最安全的选择。由于复制省略,它的效率并不比参考选项低。

引用选项的主要危险在于,如果更改了函数以返回引用,则ab可能会成为悬空引用。

答案 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引用时,临时对象的生命周期将扩展为与引用相同。

至于参考指向内存的位置,我猜它可能因实现而异。但重要的是临时对象不再是“临时对象”,尽管你无法改变它。