![](/img/trans.png)
[英]List initialization, Initializer_list and related questions in 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 来做到这一点)
列表初始化
否则,如果花括号初始化列表为空并且 T 是具有默认构造函数的类类型,则执行值初始化。
值初始化
在所有情况下,如果使用空大括号 {} 并且 T 是聚合类型,则执行聚合初始化而不是值初始化。
聚合初始化(这似乎不是我的情况,因此它不会将成员初始化为零)
聚合是以下类型之一:
- 类类型(通常为结构体或联合体),具有
- 没有用户声明的构造函数
对遗留代码最简单且不易出错的修改是什么,我需要解决在初始化之前使用某些类成员的问题?
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;
}
我是否正确理解,如果我定义了一个构造函数,它不会执行零初始化?
是的。
请注意, T
不是聚合,因为它包含用户提供的构造函数。 作为值初始化的效果:
如果 T 是没有默认构造函数或具有用户提供或删除的默认构造函数的类类型,则该对象是默认初始化的;
如果 T 是具有既不是用户提供也不是删除的默认构造函数的类类型(即,它可能是具有隐式定义或默认默认构造函数的类),则该对象被零初始化,然后是默认的-如果它有一个非平凡的默认构造函数,则初始化;
T
包含一个用户提供的默认构造函数,然后应用 #1(但不是 #2 首先执行零初始化)。
在默认初始化中,用户提供的默认构造函数用于初始化对象。 默认构造函数不对数据成员执行初始化,它们被初始化为不确定的值。
零初始化是一种特殊情况。 该标准仅保证成员属性被默认初始化。 对于类对象,它确实意味着将调用默认构造函数。 但是对于基本类型对象,默认初始化只是......根本没有初始化。 如果你需要它,你必须明确要求它:
T(): x(0), y(0) {
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.