为什么临时对象的生命周期不会延长到封闭对象的生命周期?

2023-12-02

我知道暂时的cannot绑定到非常量引用,但它can be绑定到 const 引用。那是,

 A & x = A(); //error
 const A & y = A(); //ok

我还知道,在第二种情况(上面)中,临时创建的生命周期A()延伸到 const 引用的生命周期(即y).

但我的问题是:

绑定到临时变量的 const 引用可以是further绑定到另一个常量引用,将临时对象的生命周期延长到第二个对象的生命周期?

我尝试了这个,但没有成功。我不太明白这一点。我写了这段代码:

struct A
{
   A()  { std::cout << " A()" << std::endl; }
   ~A() { std::cout << "~A()" << std::endl; }
};

struct B
{
   const A & a;
   B(const A & a) : a(a) { std::cout << " B()" << std::endl; }
   ~B() { std::cout << "~B()" << std::endl; }
};

int main() 
{
        {
            A a;
            B b(a);
        }
        std::cout << "-----" << std::endl;
        {
            B b((A())); //extra braces are needed!
        }
}

Output (ideone):

 A()
 B()
~B()
~A()
-----
 A()
 B()
~A()
~B()

输出差异?为什么是临时对象A()在对象之前被破坏b在第二种情况下?标准 (C++03) 是否讨论了这种行为?


该标准考虑了两种延长临时生命周期的情况:

§12.2/4 有两种上下文,其中临时变量在与完整表达式末尾不同的点被销毁。第一个上下文是当表达式作为定义对象的声明符的初始值设定项出现时。在这种情况下,保存表达式结果的临时变量将持续存在,直到对象的初始化完成。 [...]

§12.2/5 第二个上下文是当引用绑定到临时对象时。 [...]

这两者都不允许您通过稍后将引用绑定到另一个 const 引用来延长临时引用的生命周期。但忽略标准并想想正在发生的事情:

临时变量是在堆栈中创建的。好吧,从技术上讲,调用约定可能意味着适合寄存器的返回值(临时)甚至可能不会在堆栈中创建,但请耐心等待。当您将常量引用绑定到临时编译器时语义上创建一个隐藏的命名变量(这就是为什么复制构造函数需要可访问,即使它没有被调用)并将引用绑定到该变量。副本是否实际制作或删除是一个细节:我们拥有的是unnamed局部变量及其引用。

如果标准允许您的用例,那么这意味着临时变量的生命周期必须一直延长,直到最后一次引用该变量。现在考虑示例的简单扩展:

B* f() {
   B * bp = new B(A());
   return b;
}
void test() {
   B* p = f();
   delete p;
}

现在的问题是临时的(我们称之为_T) 绑定在f(),它的行为就像一个局部变量。引用绑定在里面*bp。现在该对象的生命周期超出了创建临时对象的函数,但是因为_T不是动态分配的,这是不可能的。

您可以尝试并推理出在此示例中延长临时对象的生命周期所需的工作量,答案是如果没有某种形式的 GC,就无法完成此任务。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么临时对象的生命周期不会延长到封闭对象的生命周期? 的相关文章

随机推荐