简体   繁体   中英

Will the compiler generated default constructor initialize the pointers in std::array to nullptr?

Is it correct that given the code below, the compiler should generate Node() which should call std::array<Node *, 100>() which should initialize all 100 pointers to nullptr.

Side note: I know that I can make that happen if I use std::array<Node *, 100> children {}; , but I am not trying to get my code to work (it already does), I am trying to make sure that it's not working by accident.

struct Node
{
    int value;
    std::array<Node *, 100> children;
}

Update:

Here pointers are garbage:

struct Node
{
    int value;
    std::array<Node *, 100> children;
}

struct Node
{
    Node() : children() {}
    int value;
    std::array<Node *, 100> children;
}

Here pointers are nullptr:

struct Node
{
    int value;
    std::array<Node *, 100> children {};
}

struct Node
{
    Node() : children{} {}
    int value;
    std::array<Node *, 100> children;
}

Please, correct me if I am wrong.

To quote cppreference on the constructor of std::array :

initializes the array following the rules of aggregate initialization (note that default initialization may result in indeterminate values for non-class T)

By declaring your variable like std::array<Node *, 100> children; you invoke the default constructor. And, according to the rules of initialization, PODs ( int , char , double , pointers, ...) are not default initialized. So no, your array will not be initialized with nullptr if you don't use aggregate initialization.

Aggregate initialization

std::array<Node *, 100> children;

invokes the default constructor, but no aggregate initializer is given so aggregate initialization won't happen. However

std::array<Node *, 100> children{}
std::array<Node *, 100> children = {};

not only invokes the default constructor, but also performs an aggregate initialization. In this case, the aggregate {} is just empty. And, following the rules of aggregate initialization, if there are less initializers than data members, every uninitialized member will be default initialized. So

Node x;
std::array<Node *, 100> children = {&x};

for example, will initialize the first array element with the pointer to x and every successive element will be default initialized to nullptr .

According to this answer , default initialization of a std::array of pointers will not initialize the pointers it contains, and their values will be indeterminate.

std::array<Node *, 100> children; // pointers are uninitialized

You can however use value initialization to initialize all the contained pointers to nullptr . On a std::array , this has the effect of value initializing each value in the array, which in turn zero-initializes every pointer.

std::array<Node *, 100> children {}; // pointers are all null

In a member initializer list, you can also do this as follows:

Node::Node() : children{/* value init array */} {/* empty c'tor body */}

Until a pointer is assigned a value, it points to a "garbage" address by default. The compiler does not assign them a default value of nullptr . In fact, it does not assign any "default" value to pointers.
Edit:
From the cppreference documentation for std::array :

note that default initialization may result in indeterminate values for non-class T

So if you use the default constructor, you need to assign each element a value of nullptr yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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