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

ebi*_*ebi 4 c++ reference return-value c++11

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

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

int main() {
  const std::string& a = foo();
}
Run Code Online (Sandbox Code Playgroud)

M.M*_*M.M 5

您的代码是非法的;非常量左值引用不能绑定到右值。这背后并没有很好的理由,这只是在 C++ 历史上很早就引入的语言规则。
MSVC 过去(可能仍然允许)允许这种绑定,我无法评论 MSVC 如何实现它。

不过,您可以绑定到其他引用类型:

std::string const &a = foo();   // (1)
std::string&& b = foo();        // (2)
Run Code Online (Sandbox Code Playgroud)

在情况 (2) 中,b直接绑定到返回值对象,该对象的生命周期扩展到 matchb的生命周期。注意:这里没有发生“移动”操作,只是绑定了一个引用。

在情况 (1) 中,从概念上讲,const std::string从返回值初始化一个临时类型,并且该临时类型的生命周期延长到 matcha的生命周期。在实践中,该副本将被省略。您的代码将表现得好像引用直接绑定到返回值。


一般来说,你应该使用值语义。std::string c = foo();是最安全的选择。由于复制省略,它的效率并不比参考选项低。

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