首先是问题:我有一个带有默认构造函数的现有结构,它将它置于有效状态。我想要一个根本不进行初始化的NoInit构造函数。现有代码对成员变量有一些初始化 - 声明期间语句,因此struct B
的示例我试图覆盖初始化 - 在声明期间语句通过显式调用std::atomic
的默认构造函数。
std::atomic
默认构造函数没有初始化:
默认构造函数很简单:不进行初始化 除了静态和线程局部对象的零初始化。
那么,为什么要调用默认构造函数导致程序集中的任何赋值?
struct A {
std::atomic<long> a;
std::atomic<long> b;
int c;
A() : a{1}, b{2}, c{3} {} // This is obviously fine.
A(DefaultInit) : a(), b(), c() {} // Should this not be similar to NoInit?
A(NoInit) {} // This is fine. Results in no code
};
第二个构造函数A(DefaultInit)
导致将0分配给三个成员变量,而A(NoInit)
导致根本没有代码。
struct B {
std::atomic<long> a{1};
std::atomic<long> b{2};
int c{3};
B() {} // This is fine.
B(NoInit) : a(), b(), c() {} // Why setting to 0? Why should it generate any assignment code at all?
};
在第二个示例中,struct B
&#39; B(NoInit)
尝试显式调用std::atomic::atomic()
,这将导致无store/mov
条指令。但这会导致为所有三个变量分配0!
当然标准确实说它是未定义的行为,如果是这样,为什么A(DefaultInit)
和A(NoInit)
之间存在差异。我希望B(NoInit)
的汇编与A(NoInit)
相同。
另外,请注意,在两种情况下,生成的程序集对于成员变量c
都没有区别。这与std::atomic
答案 0 :(得分:2)
你不能真正“明确地调用构造函数”。您只能为对象指定初始值设定项,构造函数调用可以作为其中的一部分进行。我说作为其中的一部分,因为一个无害的初始化器可以传达比人们想象的更多的意义。在这种情况下:
B(NoInit) : a(), b(), c() {}
初始值设定项()
表示您value-initialize每个成员。值初始化需要首先零初始化(从C ++ 11开始)。虽然有时会涉及何时以及何种初始化的确切情况和条件,但您可以在链接的文章中阅读它们。
在您的特定情况下,对于std::atomic
类型,会发生这种情况:
如果
T
是一个类型,默认构造函数不是 用户提供或删除(也就是说,它可能是一个带有 对象是隐式定义或默认的默认构造函数 零初始化然后如果它有一个默认初始化 非平凡的默认构造函数;
对于普通int
,就是这样:
否则,该对象被零初始化。
最终会占到你看到的所有三个零。
如果你不想看到零初始化,你可以告诉两个选项。两者都是对初始化器规则的轻微利用:
valueless_initialization
样板