默认构造函数(由编译器创建)是否初始化内置类型?
答案 0 :(得分:162)
隐式定义(由编译器)类的默认构造函数不初始化内置类型的成员。
但是,您必须记住,在某些情况下,可以通过其他方式执行类实例的初始化。不是默认构造函数,也不是构造函数。
例如,人们普遍认为对于类C
,语法C()
总是调用默认构造函数。但实际上,语法C()
执行类实例的所谓值初始化。如果它是用户声明的,它将仅调用默认构造函数。 (那是在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);
答案 1 :(得分:18)
出于所有实际目的 - 没有。
然而,对于技术上符合C ++标准的实现,答案是它取决于对象是否是POD以及如何初始化它。 根据C ++标准:
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节
答案 2 :(得分:16)
我不太确定你的意思,但是:
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
}
在我说“未初始化”的每种情况下 - 您可能会发现编译器为其提供了一致的值,但标准并不要求它。
很多挥手都被包括在我身边,关于内置类型“有效”的默认构造函数。实际上,默认初始化和值初始化是标准中定义的术语,我个人每次都必须查找。只有标准中定义的类具有隐式默认构造函数。
答案 3 :(得分:1)
根据标准,除非您在初始化列表
中明确初始化,否则它不会答案 4 :(得分:1)
正如前面的发言者所说 - 不,它们没有被初始化。
这实际上是真正奇怪错误的来源,因为现代操作系统倾向于用零填充新分配的内存区域。如果你期望,它可能第一次工作。但是,当您的应用程序继续运行delete
- ing和new
- 对象时,您迟早会遇到期望为零但从早期对象的非零剩余的情况
那么,为什么会这样,是不是所有new
- 新分配的数据?是的,但并非总是来自操作系统。操作系统倾向于使用更大的内存块(例如,每次4MB),因此所有微小的单字 - 这里 - 三字节 - 那里的分配和解除分配都在uyserspace中处理,因此不会被清零。
PS。我写了“倾向于”,即你第一次不能依靠成功......
答案 5 :(得分:-5)
从技术上讲,它确实初始化它们 - 使用它们的默认构造函数,除了为它们分配内存之外什么都不做。
如果你想知道的是int
s是否设置为0,那么答案就是“不”。
答案 6 :(得分:-8)
没有。默认构造函数分配内存并调用任何父项的无参数构造函数。