默认构造函数(由编译器创建)是否初始化内置类型?
隐式定义(由编译器定义)的类的默认构造函数不会初始化内置类型的成员。
但是,请记住,在某些情况下,可以通过其他方式对类的实例进行初始化。不是默认的构造函数,也不是构造函数。
例如,人们普遍认为,对于类C
而言,语法C()
始终会调用默认构造函数。但是实际上,语法C()
执行类实例的所谓的[[value-initialization。如果它是user-declared,它将仅调用默认构造函数。 (在C ++ 03中。在C ++ 98中-仅当类为非POD时)。如果该类没有用户声明的构造函数,则C()
将不会调用编译器提供的默认构造函数,而是将执行一种完全不涉及C
构造函数的特殊初始化。相反,它将直接对类的每个成员进行值初始化。对于内置类型,它导致零初始化。
class C {
int x;
};
然后,编译器将隐式提供一个。编译器提供的构造函数将不执行任何操作,这意味着它不会初始化C::x
C c; // Compiler-provided default constructor is used // Here `c.x` contains garbage
尽管如此,以下初始化零初始化将
x
,因为它们使用了显式的()
初始化器C c = C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(c.x == 0);
C *pc = new C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(pc->x == 0);
()
初始化程序的行为在C ++ 98和C ++ 03之间在某些方面有所不同,但在这种情况下没有区别。对于上述类C
,它将是相同的:()
初始化程序对C::x
进行零初始化。当然,不涉及构造函数而执行的初始化的另一个示例是聚合初始化
C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. assert(c.x == 0); C d{}; // C++11 style aggregate initialization. assert(d.x == 0);
MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized
但是,在现实世界中,这没有得到很好的支持,因此请不要使用它。
标准的相关部分是8.5.5和8.5.7节
struct A { int x; };
int a; // a is initialized to 0
A b; // b.x is initialized to 0
int main() {
int c; // c is not initialized
int d = int(); // d is initialized to 0
A e; // e.x is not initialized
A f = A(); // f.x is initialized to 0
}
在每种情况下,我说“未初始化”-您可能会发现编译器为其提供了一个一致的值,但标准不需要它。包括我在内,很多人都在谈论内置类型如何“有效”地具有默认构造函数。实际上,默认初始化和值初始化是标准中定义的术语,我个人必须每次都进行查询。标准中仅将类定义为具有隐式默认构造函数。
这实际上是真正奇怪的错误的来源,因为现代OS倾向于用零填充新分配的内存区域。如果您期望如此,它可能会在第一次使用。但是,随着您的应用程序不断运行,delete
-ing和new
-ing对象,您迟早会遇到以下情况:您期望零,但存在来自较早对象的非零残差。
所以,为什么这不是新分配的所有new
版本的数据?是的,但并非总是来自操作系统。操作系统倾向于使用更大的内存块(例如一次4MB),因此所有微小的单字(这里为三个字节)的分配和释放都在uyserspace中处理,因此不会被清零。
PS。我写了“倾向于”,即您第一次都不能依靠成功...
如果您想知道的是int
是否将它们设置为合理的值,例如0,则答案为“否”。