编译器创建的默认构造函数会初始化内置类型吗?
编译器创建的默认构造函数会初始化内置类型吗?
编译器隐式定义的类默认构造函数不会初始化内置类型的成员变量。
然而,你需要记住,在某些情况下,类的实例可以通过其他方式进行初始化。既不是默认构造函数,也不是任何构造函数。
例如,有一种普遍的错误观念认为,对于类 C
,语法 C()
总是调用默认构造函数。实际上,语法 C()
执行所谓的值初始化,而仅当它是用户声明的时才会调用默认构造函数。(这是在C++03中。在C++98中,仅适用于非POD类)。如果类没有用户声明的构造函数,则 C()
将不会调用编译器提供的默认构造函数,而是执行一种不涉及 C
构造函数的特殊初始化。相反,它将直接值初始化类的每个成员。对于内置类型,它将导致零初始化。
例如,如果你的类没有用户声明的构造函数
class C {
public:
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);
我不太确定你的意思,但是:
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
}
在我说“未初始化”的每种情况下 - 你可能会发现你的编译器给出了一个一致的值,但是标准并不要求它。从实际目的来看 - 不行。
然而,对于符合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节。
正如之前的发言者所说 - 不,它们没有被初始化。
这实际上是一个非常奇怪的错误源,因为现代操作系统倾向于用零填充新分配的内存区域。如果你期望这样做,第一次可能会成功。然而,随着你的应用程序不断运行,delete
和new
对象,你迟早会遇到这样一种情况:你期望得到零,但实际上却有一个非零的残留物来自先前的对象。
那么,为什么会这样呢?难道所有new
的数据都是新分配的吗?是的,但并不总是来自操作系统。操作系统倾向于使用更大的内存块(例如每次4MB),因此所有微小的单词-三个字节-这里分配和释放都在用户空间处理,因此不会被清零。
PS. 我写了“倾向于”,也就是说,你甚至不能指望第一次就成功...
从技术上讲,它确实会初始化它们——通过使用它们的默认构造函数,这个构造函数仅仅为它们分配内存。
如果你想知道的是它们是否被设置为像int
的0这样合理的值,那么答案是“不”。
C c{}
会将x
初始化为0
吗? - towiC() = default;
,它会如何工作?这仍然会对new C();
执行值初始化并对new C;
执行默认初始化吗? - Mark IngramC() = default;
,那么对于new C();
你会得到值初始化,对于new C;
你会得到默认初始化。参考:https://dev59.com/C1gQ5IYBdhLWcg3w6IEH#42049188 - Chris NoletC
是 POD 的情况。如果这个答案能提到当C
不是POD或非标准布局时情况会如何变化,那就更好了。 - Konrad Rudolph