不允许绑定到初始化列表中的引用的临时存在于actor结束之后的理由是什么?



简单示例:

struct A
{
   A() : i(int()) {}
   const int& i;
};

gcc错误:

到' a::i'的临时绑定只会持续到构造函数退出

Rule from 12.2p5:

构造函数中的引用成员的临时绑定Ctor-initializer(12.6.2)一直存在,直到构造函数退出。

有人知道这条规则的基本原理吗?在我看来,允许临时对象存活到引用对象死亡会更好。

我不认为not扩展到对象生命周期需要解释。恰恰相反!

临时对象的生存期扩展仅扩展到其外围作用域,这既自然又有用。这是因为我们严格控制了接收引用变量的生命周期。相比之下,类成员根本不在"作用域中"。想象一下:

int foo();
struct Bar
{
    Bar(int const &, int const &, int const &) : /* bind */ { }
    int & a, & b, & c;
};
Bar * p = new Bar(foo(), foo(), foo());

foo()临时对象定义一个有意义的生命周期扩展几乎是不可能的。

相反,我们的默认行为是foo()临时的生存期扩展到包含它的完整表达式的末尾,而不是进一步。

构造函数初始化列表中的int()位于堆栈上。

一旦设置了该值,int()将超出作用域,并且引用将无效。

它将驻留在什么内存中?

要按照你建议的方式工作,它不能在堆栈上,因为它必须比任何单个函数调用存活的时间都长。它不能放在内存结构体A之后,因为它无法知道A是如何分配的。

在最好的情况下,它必须变成一个秘密堆分配。这将在析构函数运行时要求进行相应的秘密回收。复制构造函数和赋值操作符也需要保密行为。

我不知道是否有人真的考虑过这样做的方式。但就我个人而言,对于一个相当模糊的功能来说,这听起来太复杂了。

相关内容

最新更新