简体   繁体   English

从函数返回的对象的延长生命周期

[英]Extended lifetime of an object returned from function

There are some unclear for me informations about extension of lifetime of an object returned from function and bound to rvalue/const lvalue reference. 关于从函数返回并绑定到rvalue / const左值引用的对象的生命周期的延长,我有一些不清楚的信息。 Information from here . 来自这里的信息。

a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. 不会扩展对return语句中函数的返回值的临时绑定:它会在返回表达式的末尾立即销毁。 Such function always returns a dangling reference. 这样的函数总是返回一个悬空引用。

If I understand correctly, the quote claims that lifetime of objects returned by return statements is not extendable. 如果我理解正确,引用声称返回语句返回的对象的生命周期是不可扩展的。 But last sentence suggest, that it only applies to functions returning references. 但最后一句话表明,它只适用于返回引用的函数。
On GCC, from the code below I get following ouput: 在海湾合作委员会,从下面的代码我得到以下输出:

struct Test
{
  Test() { std::cout << "creation\n"; }
  ~Test() { std::cout << "destruction\n"; }
};

Test f()
{
    return Test{};   
}

int main()
{
    std::cout << "before f call\n";
    Test && t = f();
    std::cout << "after f call\n";
}

before f call
creation
after f call
destruction

So it looks like the lifetime got extended. 所以看起来生命延长了。
Should the lifetime of temporary object bound to such reference be extended? 是否应延长与此类参考相关的临时对象的生命周期? Also could you provide any more clear source of informations? 您还可以提供更明确的信息来源吗?

So it looks like the lifetime got extended. 所以看起来生命延长了。

The code is pretty valid, but note that the object whose lifetime got extended is not the temporary object created inside the function f() by Test{} , it's the returned object by the function f() . 代码非常有效,但请注意,其生命周期扩展的对象不是Test{}在函数f()内创建的临时对象,它是函数f()返回的对象。 That returned object is move-constructed from the temporary object, then gets bound to t and lifetime gets extended. 返回的对象是从临时对象移动构造的,然后绑定到t并且生命周期得到扩展。 BTW the returned object is returned by value, and it's a temporary too. BTW返回的对象是按值返回的,它也是临时的。

For observation you can add move constructor manually: 要观察,您可以手动添加移动构造函数:

struct Test
{
  Test() { std::cout << "creation\n"; }
  ~Test() { std::cout << "destruction\n"; }
  Test(Test&&) { std::cout << "move\n"; }
};

and compile and run with forbidding copy elision mode, the result is: 并使用禁止复制省略模式编译和运行,结果是:

before f call
creation      // the temporary created inside f
move          // return object move-constructed
destruction   // the temporary destroyed
after f call
destruction   // the returned object destroyed

LIVE 生活


Quotes from the standard, §15.2/6 Temporary objects [class.temporary] : 标准引用, §15.2/ 6临时对象[class.temporary]

The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except: 绑定引用的临时对象或绑定引用的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:

(6.1) A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call. (6.1)绑定到函数调用中的引用参数的临时对象将持续存在,直到包含该调用的完整表达式完成。

(6.2) The lifetime of a temporary bound to the returned value in a function return statement is not extended; (6.2)函数返回语句中返回值的临时绑定的生存期不会延长; the temporary is destroyed at the end of the full-expression in the return statement. 临时在return语句中的full-expression结束时被销毁。

(6.3) A temporary bound to a reference in a new-initializer persists until the completion of the full-expression containing the new-initializer. (6.3)new-initializer中对引用的临时绑定一直持续到包含new-initializer的full-expression完成为止。 [ Example: [例如:

 struct S { int mi; const std::pair<int,int>& mp; }; S a { 1, {2,3} }; S* p = new S{ 1, {2,3} }; // Creates dangling reference 

— end example ] [ Note: This may introduce a dangling reference, and implementations are encouraged to issue a warning in such a case. - 结束示例] [注意:这可能会引入悬空引用,并鼓励实现在这种情况下发出警告。 — end note ] - 结束说明]

Quoting from a GOTW article 引自GOTW的文章

A temporary object lasts only until the end of the full expression in which it appears. 临时对象仅持续到它出现的完整表达式的结尾。 However, C++ deliberately specifies that binding a temporary object to a reference to const (or ravlue reference) on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself, and thus avoids what would otherwise be a common dangling-reference error. 但是,C ++故意指定将临时对象绑定到对堆栈上的const(或ravlue引用)的引用会延长临时对生命周期的生命周期,从而避免了常见的悬空引用错误。 。

string f() { return "abc"; }

void g() {
const string& s = f();
  cout << s << endl;    // can we still use the "temporary" object?
}

In the example above, the temporary returned by f() lives until the closing curly brace. 在上面的示例中,f()返回的临时值一直持续到结束大括号。 (Note this only applies to stack-based references. It doesn't work for references that are members of objects.) (注意,这仅适用于基于堆栈的引用。它不适用于作为对象成员的引用。)

For legalese, read this SO answer 对于法律术语,请阅读此SO答案

The answer applies to both local const references and rvalue references 答案同时适用于本地常量引用和右值引用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM