隐式声明的默认构造函数采用什么形式?
What Form Does the Implicitly-Declared Default Constructor Take?
假设我正在使用这个玩具示例:
struct Foo {
int member;
};
我知道默认构造函数不会默认初始化 member
。因此,如果我这样做,member
仍未初始化:const Foo implicit_construction
。 顺便说一句,这似乎工作正常:const Foo value_initialization = Foo()
虽然我的理解是这实际上并没有使用默认构造函数。
如果我像这样更改 Foo
:
struct Foo {
Foo() = default;
int member;
};
我尝试做 const Foo defaulted_construction
,不出所料,它的行为与 implicit_construction
完全相同,member
未初始化。
最后,如果我将 Foo
更改为:
struct Foo {
Foo(){};
int member;
};
我这样做:const Foo defined_construction
member
是 零初始化。我只是想弄清楚隐式定义的构造函数是什么样子的。我本来会是 Foo(){}
。不是这样吗?是否有其他黑魔法使我定义的构造函数的行为与默认构造函数不同?
编辑:
也许我在这里被误导了。 defaulted_construction
is definitely uninitialized.
While defined_construction
is definitely initialized.
我认为这是标准化行为,这是不正确的吗?
您遇到的是 default initialization,它的规则是(强调我的):
- if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
- if T is an array type, every element of the array is default-initialized;
- otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
编辑,响应以下 OP 的请求:
请注意 declaring a constructor = default
不会改变这种情况(再次强调我的):
Implicitly-defined default constructor
If the implicitly-declared default constructor is not defined as deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used, and it has exactly the same effect as a user-defined constructor with empty body and empty initializer list. That is, it calls the default constructors of the bases and of the non-static members of this class.
由于默认构造函数有一个空的初始化列表,它的成员满足conditions for default initialization:
Default initialization is performed in three situations:
...
3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.
另请注意,在通过实验确认这一点时必须小心,因为 int
的 default-initialized 值完全有可能为零。特别是,你提到了这个:
struct Foo {
Foo(){};
int member;
} foo;
结果为 value-initialization,但事实并非如此;这里,member
是默认初始化的。
编辑 2:
注意以下区别:
struct Foo {
int member;
};
Foo a; // is not value-initialized; value of `member` is undefined
Foo b = Foo(); // IS value-initialized; value of `member` is 0
可以通过遵循 value-initialization 的规则来理解此行为:
Value initialization is performed in these situations:
1,5) when a nameless temporary object is created with the initializer consisting of an empty pair of parentheses;
Form 1 (T();
)是上面=
右边用来初始化b
.
的表格
The effects of value initialization are:
1) if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;
2) 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;
3) if T is an array type, each element of the array is value-initialized;
4) otherwise, the object is zero-initialized.
最后,请注意在我们之前的示例中:
struct Foo {
Foo(){}; // this satisfies condition (1) above
int member;
};
Foo f = Foo();
现在,条件 (1) 适用,而是调用我们的(空)用户声明的构造函数。由于此构造函数未初始化 member
,因此 member
被默认初始化(因此其初始值未定义)。
假设我正在使用这个玩具示例:
struct Foo {
int member;
};
我知道默认构造函数不会默认初始化 member
。因此,如果我这样做,member
仍未初始化:const Foo implicit_construction
。 顺便说一句,这似乎工作正常:const Foo value_initialization = Foo()
虽然我的理解是这实际上并没有使用默认构造函数。
如果我像这样更改 Foo
:
struct Foo {
Foo() = default;
int member;
};
我尝试做 const Foo defaulted_construction
,不出所料,它的行为与 implicit_construction
完全相同,member
未初始化。
最后,如果我将 Foo
更改为:
struct Foo {
Foo(){};
int member;
};
我这样做:const Foo defined_construction
member
是 零初始化。我只是想弄清楚隐式定义的构造函数是什么样子的。我本来会是 Foo(){}
。不是这样吗?是否有其他黑魔法使我定义的构造函数的行为与默认构造函数不同?
编辑:
也许我在这里被误导了。 defaulted_construction
is definitely uninitialized.
While defined_construction
is definitely initialized.
我认为这是标准化行为,这是不正确的吗?
您遇到的是 default initialization,它的规则是(强调我的):
- if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
- if T is an array type, every element of the array is default-initialized;
- otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
编辑,响应以下 OP 的请求:
请注意 declaring a constructor = default
不会改变这种情况(再次强调我的):
Implicitly-defined default constructor
If the implicitly-declared default constructor is not defined as deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used, and it has exactly the same effect as a user-defined constructor with empty body and empty initializer list. That is, it calls the default constructors of the bases and of the non-static members of this class.
由于默认构造函数有一个空的初始化列表,它的成员满足conditions for default initialization:
Default initialization is performed in three situations:
...
3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.
另请注意,在通过实验确认这一点时必须小心,因为 int
的 default-initialized 值完全有可能为零。特别是,你提到了这个:
struct Foo {
Foo(){};
int member;
} foo;
结果为 value-initialization,但事实并非如此;这里,member
是默认初始化的。
编辑 2:
注意以下区别:
struct Foo {
int member;
};
Foo a; // is not value-initialized; value of `member` is undefined
Foo b = Foo(); // IS value-initialized; value of `member` is 0
可以通过遵循 value-initialization 的规则来理解此行为:
Value initialization is performed in these situations:
1,5) when a nameless temporary object is created with the initializer consisting of an empty pair of parentheses;
Form 1 (T();
)是上面=
右边用来初始化b
.
The effects of value initialization are:
1) if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;
2) 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;
3) if T is an array type, each element of the array is value-initialized;
4) otherwise, the object is zero-initialized.
最后,请注意在我们之前的示例中:
struct Foo {
Foo(){}; // this satisfies condition (1) above
int member;
};
Foo f = Foo();
现在,条件 (1) 适用,而是调用我们的(空)用户声明的构造函数。由于此构造函数未初始化 member
,因此 member
被默认初始化(因此其初始值未定义)。