什么时候临时生命周期扩展在现代C++中有用?

Ria*_*iaD 7 c++ lifetime temporary-objects

在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.
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,什么时候有用,例如何时是代码

A get_a();
const A& a = get_a();
Run Code Online (Sandbox Code Playgroud)

比代码更好

A get_a();
A a = get_a();
Run Code Online (Sandbox Code Playgroud)

以什么方式(例如更快,更小的二进制大小等)?应该是什么A,get_a以及调用后的代码get_a

我已经手工测试了几个案例,并且在每种情况下它似乎具有相同数量的副本和移动.

让我们将这个问题限制为当前的C++标准,现代版本的编译器和构建并启用了优化(O2,O3或其他编译器的等价物)

Nic*_*las 6

如果你确切地知道发生了什么,那么将prvalues有意识地延长到这样的命名堆栈变量是没有用的.这意味着如果您不确切知道发生了什么,它会很有用.

说,你是一个模板功能.并且用户应该给你一些具有get成员函数的对象,该成员函数返回一些符合某些预期行为的类型.问题:确实get返回引用或prvalue?

答:你不在乎.它是否返回prvalue或引用并不重要; 重要的是它返回的东西可以按照你期望的方式进行操纵.obj.get() = 10;例如,你可能希望工作.

也许get返回对象的引用.或者,也许它返回一个prvalue这是一个代理对象,行为像一个参考.在上面的例子中,它可能有一个operator=过载,所以你可以分配给它.你用户不在乎.

那么,如果你想在get(短)时间内存储什么回报会怎样?好吧,你不想这样做auto x = obj.get();; 如果它返回了一个实际的引用,你会得到一个引用的副本,这可能不是你想要的.所以你这样做auto &&x = obj.get();.Lifetime扩展允许它与代理prvalue对象一样工作,就像实际引用一样.

  • @PaulSanders:如果您希望能够执行 `obj.get() = 5;` 来为 `obj` 赋值,则 `auto x = obj.get(); x = 5;` 做同样的事情吗?如果“get”的返回是代理,那么是的。如果“get”的返回是语言引用,则不是。您使用“auto&amp;&amp;”来指示您想要准确存储“get”返回的内容。 (2认同)