// 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: 31385t2实例的成员不是零初始化的(我想要实现的)。我是否正确理解,如果我定义了一个构造函数,它将不会执行零初始化?(我知道如何使用显式默认值实现初始化为零。问题是为什么我不能使用init列表)
列表初始化
否则,如果大括号-init-列表为空且T是具有默认构造函数的类类型,则执行值初始化。
值初始化
在所有情况下,如果使用空大括号{}且T是聚合类型,则执行聚合初始化而不是值初始化。
聚合-初始化(这似乎不是我的情况,因此它没有将成员初始化为零)
聚合是下列类型之一:
什么是最简单和较少错误的旧代码修改,在这里,我需要解决一些类成员在初始化前被使用的问题?
发布于 2021-11-02 10:39:45
我是否正确理解,如果我定义了一个构造函数,它将不会执行零初始化?
是。
请注意,T不是聚合的,因为它包含用户提供的构造函数。作为值初始化的作用
T包含用户提供的默认构造函数,然后应用#1 (但不是首先执行零初始化的#2 )。
在默认初始化中,用户提供的默认构造函数用于初始化对象.默认构造函数不对数据成员执行初始化,而是将其初始化为不确定值。
发布于 2021-11-02 09:55:24
t2的数据成员具有垃圾值。这是因为它们是内置类型的,而您并没有显式地将它们降级。解决办法是:
解决方案1:使用构造函数初始化程序列表
T(): x(0), y(0){
std::cout << "T() constr called..." << std::endl;
};解决方案2:使用类内初始化器
int x = 0, y = 0;这就是为什么建议:
始终在块/本地范围内初始化内置类型。
如果您使用上述任何一个给定的解决方案,则输出如下:
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;
}发布于 2021-11-02 10:07:14
零初始化是一种特例。标准只保证默认初始化成员属性。对于类对象,这实际上意味着将调用默认构造函数。但是对于基本类型对象,默认初始化只是..。根本没有初始化。如果你需要它,你必须明确地要求它:
T(): x(0), y(0) {
...https://stackoverflow.com/questions/69808364
复制相似问题