值初始化是否适用于原子对象?
Does value initialization work for atomic objects?
这里的工作,我的意思是std::atomic<T> a{}
有效地零初始化a
。一直这么想,一直到才开始实际使用。在解释我对此的理解之前,我想表明,至少 gcc 和 clang 在实践中是这样做的。
#include <cstring>
#include <atomic>
#include <iostream>
int main() {
using atomic = std::atomic<int>;
auto p = (atomic*)operator new(sizeof(atomic));
std::memset(p, -1, sizeof(atomic));
new(p) atomic{};
std::cout << p->load() << std::endl;
}
以下是我对为什么这应该起作用的解释(当然,您可能不这么认为)。标准说
In the following operation definitions:
- an A refers to one of the atomic types.
[...]
A::A() noexcept = default;
Effects: leaves the atomic object in an uninitialized state. [ Note: These semantics ensure compatibility with C. — end note ]
它基本上是说默认构造函数是微不足道的,什么都不做。我对此没有意见,但我不明白这如何使值初始化不适用。根据cppref,值初始化的影响包括(强调我的):
if T is a class type with a default constructor that is neither
user-provided nor deleted (that is, it may be a class with an
implicitly-defined or defaulted default constructor), the object is
zero-initialized and then it is default-initialized if it has a
non-trivial default constructor;
std::atomic
有默认的默认构造函数,所以对象是
- 零初始化然后
- 如果它有一个非平凡的默认构造函数,它就是默认初始化的。
第 2 点在这里不适用,因为默认的默认构造函数是微不足道的,但我没有看到任何使第 1 点无效的语句。我的理解正确还是我遗漏了什么?
最终值初始化情况的症结在[dcl.init]/7,要点 1 和 2:
To value-initialize an object of type T means:
- if T is a (possibly cv-qualified) class type (Clause [class]) with a user-provided constructor ([class.ctor]), then the default constructor
for T is called (and the initialization is ill-formed if T has no
accessible default constructor);
- T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if
T's implicitly-declared default constructor is non-trivial, that
constructor is called.
- ...
应用上面两个项目符号中的哪一个取决于 c'tor 是 user-provided。我在对其他答案的评论中不记得的是 = default;
应用于该问题时的复杂性。如果我们看一下 [dcl.fct.def.default]/4 给出的定义(强调我的):
Explicitly-defaulted functions and implicitly-declared functions are
collectively called defaulted functions, and the implementation shall
provide implicit definitions for them ([class.ctor] [class.dtor],
[class.copy]), which might mean defining them as deleted. A special
member function is user-provided if it is user-declared and not
explicitly defaulted or deleted on its first declaration. A
user-provided explicitly-defaulted function (i.e., explicitly
defaulted after its first declaration) is defined at the point where
it is explicitly defaulted; if such a function is implicitly defined
as deleted, the program is ill-formed. [ Note: Declaring a function as
defaulted after its first declaration can provide efficient execution
and concise definition while enabling a stable binary interface to an
evolving code base. — end note ]
我们看到 atomic
的默认 c'tor 不是用户提供的 ,因为它被声明为默认,而不是被声明然后定义为违约。所以 [dcl.init]/7 的第二个项目符号是适用的,对象是 zero-initialized,然后是(非)调用(普通默认)构造函数,它什么也不做。
这里的工作,我的意思是std::atomic<T> a{}
有效地零初始化a
。一直这么想,一直到
#include <cstring>
#include <atomic>
#include <iostream>
int main() {
using atomic = std::atomic<int>;
auto p = (atomic*)operator new(sizeof(atomic));
std::memset(p, -1, sizeof(atomic));
new(p) atomic{};
std::cout << p->load() << std::endl;
}
以下是我对为什么这应该起作用的解释(当然,您可能不这么认为)。标准说
In the following operation definitions:
- an A refers to one of the atomic types.
[...]
A::A() noexcept = default;
Effects: leaves the atomic object in an uninitialized state. [ Note: These semantics ensure compatibility with C. — end note ]
它基本上是说默认构造函数是微不足道的,什么都不做。我对此没有意见,但我不明白这如何使值初始化不适用。根据cppref,值初始化的影响包括(强调我的):
if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;
std::atomic
有默认的默认构造函数,所以对象是
- 零初始化然后
- 如果它有一个非平凡的默认构造函数,它就是默认初始化的。
第 2 点在这里不适用,因为默认的默认构造函数是微不足道的,但我没有看到任何使第 1 点无效的语句。我的理解正确还是我遗漏了什么?
最终值初始化情况的症结在[dcl.init]/7,要点 1 和 2:
To value-initialize an object of type T means:
- if T is a (possibly cv-qualified) class type (Clause [class]) with a user-provided constructor ([class.ctor]), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
- T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is non-trivial, that constructor is called.
- ...
应用上面两个项目符号中的哪一个取决于 c'tor 是 user-provided。我在对其他答案的评论中不记得的是 = default;
应用于该问题时的复杂性。如果我们看一下 [dcl.fct.def.default]/4 给出的定义(强调我的):
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy]), which might mean defining them as deleted. A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
我们看到 atomic
的默认 c'tor 不是用户提供的 ,因为它被声明为默认,而不是被声明然后定义为违约。所以 [dcl.init]/7 的第二个项目符号是适用的,对象是 zero-initialized,然后是(非)调用(普通默认)构造函数,它什么也不做。