【问题标题】:Need some clarification with 8.5.p7 in the C++11 Standard需要对 C++11 标准中的 8.5.p7 进行一些说明
【发布时间】:2013-07-17 23:48:31
【问题描述】:

C++11 标准第 8.5p7 段规定:

对 T 类型的对象进行值初始化意味着:

  • 如果 T 是具有用户提供的构造函数的(可能是 cv 限定的)类类型(第 9 条) (12.1),然后调用 T 的默认构造函数(并且 如果 T 没有可访问的默认值,则初始化格式错误 构造函数);

  • 如果 T 是(可能是 cv 限定的)非联合类类型 如果没有用户提供的构造函数,那么对象是 零初始化 并且,如果 T 的隐式声明的默认构造函数 是不平凡的,该构造函数被调用。

  • 如果 T 是数组类型, 那么每个元素都是值初始化的;

  • 否则,对象为 零初始化。

我无法理解上面的粗体字符。 T 的隐式默认构造函数的额外调用如何改变在这种情况下刚刚发生的零初始化?

【问题讨论】:

    标签: c++ c++11 initialization


    【解决方案1】:

    这是一个具体的例子:

    class A {
        int a;
    public:
        A() : a(1) {}
    };
    
    class B {
        int b;
        A c;
    };
    

    B 属于这一类——它是一个非联合类类型,没有用户提供的构造函数。所以如果一个B是值初始化的,它首先会被初始化为零(所以bc.a都会被设置为0),然后会调用默认的构造函数(会调用A的构造函数并将c.a 设置为1)。

    根据as-if 规则,优化器可能会将这些组合为一个步骤(将b 设置为0,c.a 设置为1),因为没有人可以看到零之间的对象初始化和默认构造函数。

    【讨论】:

    • 需要注意的是VC++并没有正确的实现这一点。 C++98 有不同的初始化规则,而 VC++ 仍然实现了这些。 bug report
    • 我花了一点时间来理解这一点,但是,是的,隐式/默认 ctor 可能调用非隐式基本 ctor 的事实是关键。来自我的 +1
    • @LightnessRacesinOrbit:成员的非隐式 ctors,而不是基数。
    • @MooingDuck:哎呀,是的。
    【解决方案2】:
    struct S {
        int a, b;
        S() : b(10) {}
    };
    
    struct T {
      S s;
    };
    
    int main() {
        S s{};
        T t{};
    }
    

    t 是值初始化的,T 没有用户提供的构造函数。然而T 的隐式声明的默认构造函数并不是微不足道的。

    s 也是初始化值,但S 有一个用户提供的构造函数。

    s.a 将具有不确定的值。但t.s.a 为零,因为在调用默认构造函数之前进行了零​​初始化。 s.bt.s.b 都设置为值 10。

    【讨论】:

      【解决方案3】:

      T 可能没有它自己的显式默认构造函数,但它可能派生自有的U,和/或有一个有的类类型V 的成员。

      【讨论】:

      • 即便如此,当对象被零初始化时,构造函数怎么能改变它?
      • 我不确定您所说的“更改对象”是什么意思。要改变某些东西,它首先必须有一个值,然后再更改为其他值。构造函数不会改变任何东西,它会建立初始值。
      • 啊 - 当它说它是零初始化时,它与Foo *foo = 0不一样?
      • 什么时候说什么是零初始化?您以粗体突出显示的文本并不表示任何内容都是零初始化的。
      • 我没有加粗文本(我不是提问者),但就在粗体文本之前它说“然后对象被零初始化”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 2016-06-16
      • 1970-01-01
      • 2014-10-02
      • 1970-01-01
      • 2011-08-02
      相关资源
      最近更新 更多