c++ - 在执行不平凡的构造函数之前引用成员

标签 c++ c++11 constructor language-lawyer

我阅读了 c++ 11 标准草案(N3242 修订版)并发现了以下声明:

(12.7 Construction and destruction). For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior.

据我了解,Foo 的默认构造函数具有未定义的行为(在一段代码 i(&a.i) 中? Foo 的构造函数并不简单(因为它是用户定义的),我指的是在执行构造函数之前的成员 a

struct A
{
    int i;
};

struct Foo
{
    A a;
    int* i;
    Foo() : a(), i(&a.i)
    {}
};

UPD:int* 类型的成员的用法可能没有那么有用(例如 int 类型更合适)

最佳答案

As I understand following default constructor of Foo has undefined behaviour (in piece of code i(&a.i)?

没有。您引用的措辞使用了“在构造函数开始执行之前”这一短语。但是,当我们在 mem-initializer 中初始化 i 时,我们是在 a 已经构造完成后进行的(因为 a 是在 i 之前声明的),所以这完全没问题。

此外,即使两个成员互换,程序仍然可以正常运行,因为 A 没有非平凡的构造函数。

如果您查看该部分中的示例,它们会阐明措辞的意图。特别是 second example :

struct W { int j; };
struct X : public virtual W { };
struct Y {
  int* p;
  X x;
  Y() : p(&x.j) {   // undefined, x is not yet constructed
    }
};

X 有一个非平凡的构造函数(因为 virtual 基),所以我们在构造它之前引用 x,但是p 的初始化就是这样做的。因此,UB。

关于c++ - 在执行不平凡的构造函数之前引用成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47015495/

相关文章:

c++ - 如何声明 constexpr C 字符串?

c++ - Windows 和 Linux 上 std::unordered_map 容器的不同行为

C++:重载下标运算符(不同的返回类型)

java - 更改构造函数参数运行时

c# - 构造函数执行前的属性初始化

c++ - char 变量的范围是多少? -127 到 127 还是 0 到 255?

c++ - 错误 : LINK: fatal error LNK1561: entry point must be defined c++

java - 如何在 java 中执行 map[u].push_back(v) (c++)?

c++ - 保留集合中最小的 n 个元素,丢弃其他元素

C++:是否可以在构造函数完成之前调用对象的函数?