简体   繁体   English

C++11 中类数据成员的默认初始化

[英]Default initialization of class data members in C++11

I'm confused about the default initialization of the class data members.我对类数据成员的默认初始化感到困惑。 Here is the sample code.这是示例代码。

#include <iostream>
#include <vector>

class A {
public:
  int i;
  A() {}
};

A a1;
A aa1[3];
std::vector<A> av1(3);

int main()
{
  A a2;
  A aa2[3];
  std::vector<A> av2(3);
  std::cout << a1.i << " " << a2.i << std::endl;          // 0         undefined
  std::cout << aa1[0].i << " " << aa2[0].i << std::endl;  // 0         undefined
  std::cout << av1[0].i << " " << av2[0].i << std::endl;  // undefined undefined
}

In the code above, only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized.上面的代码中只有a1.iaa1[0~2].i被初始化为0,其他的都没有初始化。 I don't know why is that happened.我不知道为什么会这样。

To be specifically, what I already know is that (From "C++ Primer"):具体来说,我已经知道的是(来自“C++ Primer”):

  • The process of initialization is:初始化过程为:

    • a1 and a2 are default initialized . a1a2默认初始化的。
    • every element of aa1 and aa2 are default initialized . aa1aa2的每个元素都是默认初始化的。
    • every element of av1 and av2 are value initialized . av1av2的每个元素都是值初始化的。
  • The process of default initialize is:默认初始化的过程是:

    • check if the variable is built-in type or class type .检查变量是内置类型还是类类型
    • for built-in type , if the variable is outside any function body, then it is initialized to 0, else the value is undefined.对于内置类型,如果变量在任何函数体之外,则将其初始化为 0,否则该值未定义。
    • for class type , if the class has default ctor, then that is called, else it is a compile error.对于类类型,如果该类具有默认构造函数,则调用它,否则为编译错误。
  • The process of value initialize is:值初始化的过程是:

    • check if the variable is built-in type or class type .检查变量是内置类型还是类类型
    • for built-in type , it is initialized to 0.对于内置类型,它被初始化为 0。
    • for class type , it is default initialized .对于类类型,它是默认初始化的。 (Which I think means if the class has default ctor, then that is called, else it is a compile error.) (我认为这意味着如果该类具有默认构造函数,则调用它,否则它是一个编译错误。)

So that when the ctor A::A() is called, how the data member A::i initialized (I guess it is default initialized)?那么当调用构造函数A::A()时,数据成员A::i是如何初始化的(我猜它是默认初始化的)? And why only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized?还有为什么只有a1.iaa1[0~2].i初始化为0,其他的都没有初始化?

when the ctor A::A() is called, how the data member A::i initialized当构造函数 A::A() 被调用时,数据成员 A::i 是如何初始化的

If no initializer is provided, the rules of default initialization apply.如果未提供初始化器,则应用默认初始化规则。 Your constructor does no initialization of A::i so it's left uninitialized;你的构造函数没有初始化A::i所以它没有被初始化; it's value is indeterminate.它的价值是不确定的。 No doubt about that.毫无疑问。 Excerpt from the documentation on default initialization :摘自关于默认初始化的文档

If T is a class type, the constructors are considered and subjected to overload resolution against the empty argument list.如果 T 是类类型,则考虑构造函数并对空参数列表进行重载解析。 The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object.选择的构造函数(默认构造函数之一)被调用以提供新对象的初始值。


why only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized?为什么只有a1.i和aa1[0~2].i被初始化为0,其他的都没有初始化?

The global data memory is initialized to zero ie the whole section is zeroed out and so you see global A::i s initialized to 0 .全局数据内存被初始化为零,即整个部分被清零,所以你看到全局A::i被初始化为0 Note that the constructor would not be doing this.请注意,构造函数不会这样做。 Excerpt from the documentation :文档摘录:

Static initialization静态初始化

[...] [...]

2) For all other non-local static and thread-local variables, Zero initialization takes place. 2) 对于所有其他非本地静态和线程本地变量, 零初始化发生。 In practice, variables that are going to be zero-initialized are placed in the.bss segment of the program image, which occupies no space on disk, and is zeroed out by the OS when loading the program.在实践中,将被零初始化的变量放在程序映像的.bss 段中,该段不占用磁盘空间,并在加载程序时由操作系统清零。

However, for the vector , the vector itself is in the non-local static memory while its elements are allocated in free store (heap) and hence their members are uninitialized too.但是,对于vectorvector本身位于非本地静态内存中,而其元素分配在自由存储(堆)中,因此它们的成员也未初始化。

Global (both static and exported) variables are zero-initialized (in practice, on usual platforms, they are in memory are which is filled with zeros at program start), if they are not explicitly initialized and don't have a constructor.全局(静态和导出)变量是零初始化的(实际上,在通常的平台上,它们在内存中,在程序启动时用零填充),如果它们没有显式初始化并且没有构造函数。

Items of vector are default-initialized, when you use the constructor you are using in your code.当您使用您在代码中使用的构造函数时,向量项是默认初始化的。

For a vector class object, both mean a constructor call.对于向量类对象,两者都意味着构造函数调用。 But for integers, first means initialized to zero, while latter means initialized with indeterminate value.但对于整数,first 表示初始化为零,而 latter 表示初始化为不确定值。 So the plain int variables in your code are zero-initialized, but the ints in the vector are default initialized.所以代码中的普通 int 变量是零初始化的,但向量中的 int 是默认初始化的。

Some links for reference:一些链接供参考:

You declare a constructor for A , so there is no default initialization of i ;您为A声明了一个构造函数,因此没有i的默认初始化; that's your responsibility in the constructor.这是你在构造函数中的责任。 The global variables get initial values of 0 because they're global.全局变量的初始值为 0,因为它们是全局的。 All globals are initialized to 0 if they aren't given an initial value by some means.如果未通过某种方式为所有全局变量赋予初始值,则所有全局变量都将初始化为 0。

The local variables and vectors get random data because that's what's in the memory on the stack (for locals) or heap (for the allocated memory that the vector uses) that is being used by those A instances.局部变量和向量获取随机数据,因为这是那些A实例正在使用的堆栈(对于局部变量)或堆(对于向量使用的分配内存)中的内存。

The initialization of an object of class type is controlled by the class, and this process is done recursively .类类型对象的初始化由类控制,这个过程是递归完成的。 Take your sample code for example, the initialization of i is controlled by A .以您的示例代码为例, i的初始化由A控制。 Since no constructor is provided, the synthesized default constructor will be used.由于未提供构造函数,因此将使用合成的默认构造函数。 And since no in-class initializers are provided, every member of A is default initialized, again, the default initialization rule is queried.并且由于没有提供类内初始化器,所以A的每个成员都被默认初始化,同样,默认初始化规则被查询。 The built-in type i will be left uninitialized.内置类型i将保持未初始化状态。 If A contains a member s of type string , then the default initialization of s is controlled by the string class ( the recursive rule takes place ).如果A包含类型为string的成员s ,则s的默认初始化由string类控制(递归规则发生)。 In this case, s will be initialized to an empty string.在这种情况下, s将被初始化为一个空字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM