在C ++中,您可以将函数的返回值(返回值,而不是引用)绑定到const引用,代码仍然有效,因为此临时的生命周期将延长到范围结束。例如
std::string get_string() {
return "abc";
}
void f() {
const std::string& str = get_string();
std::cout << str; // valid, str is not dangling reference.
}
我的问题是,什么时候有用,例如代码是什么时候
A get_a();
const A& a = get_a();
比代码
更好A get_a();
A a = get_a();
以什么方式(例如更快,更小的二进制大小等)?调用A
后,get_a
,get_a
和代码的实现应该是什么?
我已经手工测试了几个案例,并且在每种情况下它似乎具有相同数量的副本和移动。
让我们将这个问题限制在当前的C ++标准,现代版本的编译器和构建时启用了优化(O2,O3或其他编译器的等价物)
答案 0 :(得分:6)
如果你确切地知道发生了什么,那么将prvalues有意识地延长到像这样的命名堆栈变量是没有用的。这意味着如果您不知道究竟发生了什么,这将非常有用。
说,你是一个模板功能。并且用户应该给你一些具有get
成员函数的对象,该函数返回一些符合某些预期行为的类型。问题:get
会返回引用还是prvalue?
答案:你不在乎。如果它返回一个prvalue或一个引用并不重要;重要的是它返回的东西可以按照你期望的方式进行操纵。例如,您可能希望obj.get() = 10;
起作用。
也许get
返回对象的引用。或者它可能返回一个prvalue,它是行为的代理对象,就像一个引用。在上面的例子中,它可能有operator=
重载,因此您可以为其分配。用户不在乎。
那么,如果你想存储get
在一段(短)时间内返回的内容,会发生什么?好吧,你不想做auto x = obj.get();
;如果它返回了一个实际的引用,你会得到一个引用的副本,这可能不是你想要的。所以你做auto &&x = obj.get();
。 Lifetime扩展允许它与代理prvalue对象一样工作,就像实际引用一样。