当它绑定到调用函数中的 const 引用时,它的返回值的生命周期如何扩展到调用函数的范围?

2021-12-21 00:00:00 pass-by-reference memory constants c++

如果从函数返回一个值(不是引用),然后将其绑定到调用函数中的 const 引用,则其生命周期将扩展到调用函数的范围."

"If you return a value (not a reference) from the function, then bind it to a const reference in the calling function, its lifetime would be extended to the scope of the calling function."

所以:案例 A

const BoundingBox Player::GetBoundingBox(void)
{
    return BoundingBox( &GetBoundingSphere() );
}

从函数 GetBoundingBox()

变体 I:(将其绑定到常量引用)

variant I: (Bind it to a const reference)

const BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox();

变体 II:(将其绑定到一个常量副本)

variant II: (Bind it to a const copy)

const BoundingBox l_Bbox = l_pPlayer->GetBoundingBox();

两者都工作正常,而且我没有看到 l_Bbox 对象超出范围.(不过,我理解在变体一中,没有调用复制构造函数,因此比变体二略好).

Both work fine and I don't see the l_Bbox object going out of scope. (Though, I understand in variant one, the copy constructor is not called and thus is slightly better than variant II).

另外,为了比较,我做了以下改动.

Also, for comparison, I made the following changes.

案例 B

BoundingBox Player::GetBoundingBox(void)
{
    return BoundingBox( &GetBoundingSphere() );
}

带有变体:我

BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox();

和二:

BoundingBox l_Bbox = l_pPlayer->GetBoundingBox();

<小时>

对象 l_Bbox 仍然没有超出范围.如何将其绑定到调用函数中的const引用,其生命周期会扩展到调用函数的范围内",真正将对象的生命周期扩展到调用函数的范围?


The object l_Bbox still does not go out scope. How does "bind it to a const reference in the calling function, its lifetime would be extended to the scope of the calling function", really extend the lifetime of the object to the scope of the calling function ?

我在这里遗漏了一些微不足道的东西吗?

Am I missing something trivial here?

推荐答案

通常,临时对象(例如由函数调用返回的对象)的生命周期会延伸到封闭表达式"的末尾.但是,对引用的临时绑定通常会将其生命周期提升"到引用的生命周期(可能是也可能不是调用函数的生命周期),但有一些例外.12.2/5临时对象"中的标准涵盖了这一点:

Normally a temporary object (such as one returned by a function call) has a lifetime that extends to the end of the "enclosing expression". However, a temporary bound to a reference generally has it's lifetime 'promoted' to the lifetime of the reference (which may or may not be the lifetime of the calling function), but there are a couple exceptions. This is covered by the standard in 12.2/5 "Temporary objects":

引用绑定的临时对象或作为临时对象绑定的子对象的完整对象的临时对象在引用的生命周期内持续存在,除非在下面指定.临时绑定到构造函数的 ctor-initializer (12.6.2) 中的引用成员会一直存在,直到构造函数退出.在函数调用 (5.2.2) 中临时绑定到引用参数会一直存在,直到包含调用的完整表达式完成.

The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.

有关详细信息,请参阅以下内容:

See the following for more information:

  • C++ 常量引用生命周期(容器适配器)
  • GotW #88:最重要的常量"的候选

一个可能有助于形象化正在发生的事情的例子:

An example that might help visualize what's going on:

#include <iostream>
#include <string>

class foo {
public:
    foo( std::string const& n) : name(n) { 
        std::cout << "foo ctor - " << name + " created
"; 
    };
    foo( foo const& other) : name( other.name + " copy") { 
        std::cout << "foo copy ctor - " << name + " created
";
    };

    ~foo() { 
        std::cout << name + " destroyed
"; 
    };

    std::string getname() const { return name; };
    foo getcopy() const { return foo( *this); };

private:
    std::string name;
};

std::ostream& operator<<( std::ostream& strm, foo const& f) {
    strm << f.getname();
    return strm;
}


int main()
{
    foo x( "x");

    std::cout << x.getcopy() << std::endl;

    std::cout << "note that the temp has already been destroyed


";

    foo const& ref( x.getcopy());

    std::cout << ref << std::endl;

    std::cout << "the temp won't be deleted until after this...

";
    std::cout << "note that the temp has *not* been destroyed yet...

";
}

显示:

foo ctor - x created
foo copy ctor - x copy created
x copy
x copy destroyed
note that the temp has already been destroyed


foo copy ctor - x copy created
x copy
the temp won't be deleted until after this...

note that the temp has *not* been destroyed yet...

x copy destroyed
x destroyed

相关文章