【问题标题】:Is it allowed to call a non-static member function in a default member initializer?是否允许在默认成员初始化程序中调用非静态成员函数?
【发布时间】:2020-03-16 10:10:57
【问题描述】:

考虑这个类:

#include <iostream>

struct foo {
    int a = 42;
    int b = bar();
    int bar() { return a; }
};

int main(){
    foo f;
    std::cout << f.a << " " << f.b;
}

它打印出预期的42 42。标准是否允许在默认成员初始化程序中调用成员函数?

以下我希望是未定义的:

struct broken {
    int a = bar();
    int b = 42;       
    int bar() { return b; }
};

不幸的是compile without warnings

【问题讨论】:

    标签: c++ constructor initialization language-lawyer member-initialization


    【解决方案1】:

    如您所见,这是合法的,但很脆弱,不推荐使用。当您为类成员指定默认初始化程序时,这些只是在类成员初始化程序列表中使用此值的语法糖。因此,如果我们查看何时可以调用成员函数,我们会发现 [class.cdtor]/1[class.cdtor]/4 声明:

    1) 对于具有非平凡构造函数的对象,在构造函数开始执行之前引用对象的任何非静态成员或基类会导致未定义的行为。对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基类会导致未定义的行为。

    4)成员函数,包括虚函数([class.virtual]),可以在构造或销毁([class.base.init])期间调用。[...]

    强调我的

    由于构造函数已经开始执行,并且我们可以调用成员函数,所以我们不在 UB 领域。

    接下来我们要考虑的是构造顺序,因为成员依赖于它。该信息在[class.base.init]/13

    然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem-initializers 的顺序无关)。

    因此,成员是按照它们在类中声明的顺序构造的,这意味着在您的第一个示例中,您在初始化之后引用a,因此您不在 UB 领域。

    在您的第二个示例中,您指的是尚未初始化的对象,而读取未初始化对象的值是未定义的行为。

    【讨论】:

      【解决方案2】:

      标准说here

      可以为正在构建的对象调用成员函数(包括虚成员函数,[class.virtual])。类似地,正在构建的对象可以是 typeid 运算符 ([expr.typeid]) 或 dynamic_cast ([expr.dynamic.cast]) 的操作数。但是,如果在基类的所有 mem-initializer 完成之前,在 ctor-initializer(或直接或间接从 ctor-initializer 调用的函数中)执行这些操作,则程序具有未定义的行为。

      由于您没有基类,因此可以为broken 调用成员函数,即使它正在构建中。 您的a 将被初始化为不确定的值。

      我有点为时过早。正如在另一个答案中看到的那样,存在一个问题,即函数从未定义行为的未初始化值中读取。所以不是这个函数本身的调用,而是它所做的就是UB。

      【讨论】:

      • 也许你错过了“但是,如果这些操作在基类的所有 mem-initializer 完成之前在 ctor-initializer(或直接或间接从 ctor-initializer 调用的函数中)中执行,程序具有未定义的行为。”。最好在答案中包含文字
      • 我可以将文本复制到答案中,但这应该对您的示例没有影响,因为它没有基类。还是我在阅读本文时错过了什么?
      • 对不起,我错过了基类的东西。不过答案应该是独立的
      • 没有伤害。感谢您的提示,我对整个事情还是有点陌生​​^^
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 2011-05-31
      相关资源
      最近更新 更多