使用复制列表初始化程序的 C++ 对象初始化
C++ object initialization with copy-list-initializer
// Example program
#include <iostream>
#include <string>
class T{
public:
int x, y;
T(){
std::cout << "T() constr called..." << std::endl;
};
T(int x, int y):x(x),y(y){
std::cout << "T(x,y) constr called..." << std::endl;
}
void inspect(){
std::cout << "T.x: " << this->x << std::endl;
std::cout << "T.y: " << this->y << std::endl;
}
};
int main()
{
T t1(5,6);
t1.inspect();
std::cout << std::endl;
T t2 = {};
t2.inspect();
}
我得到以下结果:
T(x,y) constr called...
T.x: 5
T.y: 6
T() constr called...
T.x: 208787120
T.y: 31385
t2
实例的成员没有被零初始化(我想要实现的)。我是否理解正确,如果我定义了构造函数,它将不会执行零初始化?
(我知道如何使用显式默认值实现初始化为零。问题是为什么我无法使用 init-list 做到这一点)
列表初始化
Otherwise, if the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
值初始化
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.
聚合初始化(这似乎不是我的情况,因此它没有将成员初始化为零)
An aggregate is one of the following types:
- class type (typically, struct or union), that has
- no user-declared constructors
什么是遗留代码最简单且不易出错的修改,我需要解决一些 class 成员在初始化之前使用的问题?
t2
的数据成员有垃圾值。这是因为它们是内置类型,您没有明确地初始化它们。解决方案是:
解决方案 1:使用构造函数初始化列表
T(): x(0), y(0){
std::cout << "T() constr called..." << std::endl;
};
解决方案 2:使用 in-class 初始化器
int x = 0, y = 0;
这就是为什么建议:
always initialize built-in type in block/local scope
如果您使用上面给出的任何解决方案,输出将是:
T(x,y) constr called...
T.x: 5
T.y: 6
T() constr called...
T.x: 0
T.y: 0
另一种解决方案是使用委托构造函数(正如@MarekR 在下面的评论中所建议的),例如:
T():T(0, 0)
{
std::cout << "T() constr called..." << std::endl;
}
零初始化是一种特殊情况。该标准仅保证成员属性被 default 初始化。对于 class 对象,这确实意味着将调用默认构造函数。但是对于基本类型对象,默认初始化只是......根本没有初始化。如果需要,您必须明确要求:
T(): x(0), y(0) {
...
Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?
是的。
请注意,T
不是聚合,因为它包含用户提供的构造函数。作为value initialization的效果:
if T is a class type with no default constructor or with a
user-provided or deleted default constructor, the object is
default-initialized;
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;
T
包含用户提供的默认构造函数,然后应用#1(但不是#2首先执行零初始化)。
在default initialization中,使用用户提供的默认构造函数来初始化对象。默认构造函数不对数据成员执行初始化,它们被初始化为不确定的值。
// Example program
#include <iostream>
#include <string>
class T{
public:
int x, y;
T(){
std::cout << "T() constr called..." << std::endl;
};
T(int x, int y):x(x),y(y){
std::cout << "T(x,y) constr called..." << std::endl;
}
void inspect(){
std::cout << "T.x: " << this->x << std::endl;
std::cout << "T.y: " << this->y << std::endl;
}
};
int main()
{
T t1(5,6);
t1.inspect();
std::cout << std::endl;
T t2 = {};
t2.inspect();
}
我得到以下结果:
T(x,y) constr called...
T.x: 5
T.y: 6
T() constr called...
T.x: 208787120
T.y: 31385
t2
实例的成员没有被零初始化(我想要实现的)。我是否理解正确,如果我定义了构造函数,它将不会执行零初始化?
(我知道如何使用显式默认值实现初始化为零。问题是为什么我无法使用 init-list 做到这一点)
列表初始化
Otherwise, if the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
值初始化
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.
聚合初始化(这似乎不是我的情况,因此它没有将成员初始化为零)
An aggregate is one of the following types:
- class type (typically, struct or union), that has
- no user-declared constructors
什么是遗留代码最简单且不易出错的修改,我需要解决一些 class 成员在初始化之前使用的问题?
t2
的数据成员有垃圾值。这是因为它们是内置类型,您没有明确地初始化它们。解决方案是:
解决方案 1:使用构造函数初始化列表
T(): x(0), y(0){
std::cout << "T() constr called..." << std::endl;
};
解决方案 2:使用 in-class 初始化器
int x = 0, y = 0;
这就是为什么建议:
always initialize built-in type in block/local scope
如果您使用上面给出的任何解决方案,输出将是:
T(x,y) constr called...
T.x: 5
T.y: 6
T() constr called...
T.x: 0
T.y: 0
另一种解决方案是使用委托构造函数(正如@MarekR 在下面的评论中所建议的),例如:
T():T(0, 0)
{
std::cout << "T() constr called..." << std::endl;
}
零初始化是一种特殊情况。该标准仅保证成员属性被 default 初始化。对于 class 对象,这确实意味着将调用默认构造函数。但是对于基本类型对象,默认初始化只是......根本没有初始化。如果需要,您必须明确要求:
T(): x(0), y(0) {
...
Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?
是的。
请注意,T
不是聚合,因为它包含用户提供的构造函数。作为value initialization的效果:
if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;
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;
T
包含用户提供的默认构造函数,然后应用#1(但不是#2首先执行零初始化)。
在default initialization中,使用用户提供的默认构造函数来初始化对象。默认构造函数不对数据成员执行初始化,它们被初始化为不确定的值。