在施工合法期间是否采取未初始化的班级成员参考?

时间:2016-06-09 11:26:58

标签: c++

来自question,我更进一步:

C* c = static_cast<C*>(malloc(sizeof(C)));

如引用的问题所述,在调用构造函数之前访问* c(其成员)是未定义的行为。但是,指针本身当然是有效的。

现在在构造函数中,成员已经可用,我应该能够取消该地址。

综合起来,我得出以下结论:

class Y;
class X
{
    Y& y;
public:
    X(Y& y) : y(y) { } // non-trivial constructor!
};
class Y
{
    X& x;
public:
    Y(X& x) : x(x) { }
};
class Z
{
    X x;
    Y y;
public:
    Z() : x(y), y(x) { } 
};

只要X的构造函数不使用未初始化的Y引用而不是将其存储在某处。

这是正确的还是我监督了一些重点(从而再次产生UB)?如果我遗漏了某些东西,如果我使用指针而不是引用它会有所作为吗?

2 个答案:

答案 0 :(得分:2)

应该没问题,但我们不允许在y内使用X(Y& y)因为它尚未初始化。

说不是UB的相关部分是:

3.7.5 / 6 n4140(重点是我的)

  

同样,在对象的生命周期开始之前但在之后   对象占用的存储空间已被分配,或之后   对象的生命周期已经结束,在存储之前就已经存在了   对象占用被重用或释放, 任何引用的glvalue   可以使用原始对象,但只能以有限的方式使用

y是左值(也是glvalue),所以上面是相关的。使用这种参考访问变量是UB。

标准也说参考有效必须(8.3.2 / 5):

  

...应初始化引用以引用有效的对象或函数。

但我没有在标准中发现什么是valid object。特别是它是否意味着它的构造函数已被调用。使用指针而不是引用似乎没有这个问题。

答案 1 :(得分:2)

这是合法的。为证明这一点,请参阅标准[basic.life]中的以下内容:

  
      
  1. 在对象的生命周期开始之前但在存储之后   对象将占用哪个已被分配,或之后   对象的生命周期已经结束,在存储之前就已经存在了   对象占用被重用或释放,任何引用的指针   可以使用对象将位于或位于的存储位置   但只是在有限的方面。对于正在建造的物体或   破坏,见12.7。否则,这样的指针指的是已分配   存储(3.7.4.2),并使用指针,就像指针一样   类型void *,定义明确。 ...
  2.         

    ...

         
        
    1. 同样,在对象的生命周期开始之前但在之后   对象占用的存储空间已被分配,或之后   对象的生命周期已经结束,在存储之前就已经存在了   对象占用被重用或释放,任何引用的glvalue   可以使用原始对象,但只能以有限的方式使用。对于对象   正在建设或破坏,见12.7。否则,这样的glvalue   指分配存储(3.7.4.2),并使用的属性   不依赖于其值的glvalue是明确定义的。
    2.         

      ...

仅提供参考属于“限制使用”的范围。 (对于生命周期尚未开始的对象)上面列出的标准。