编译器生成的默认构造函数会将 std::array 中的指针初始化为 nullptr 吗?
Will the compiler generated default constructor initialize the pointers in std::array to nullptr?
给定下面的代码是否正确,编译器应该生成 Node()
,它应该调用 std::array<Node *, 100>()
,它应该将所有 100 个指针初始化为 nullptr。
旁注:我知道如果我使用 std::array<Node *, 100> children {};
,我可以做到这一点,但我并没有试图让我的代码工作(它已经工作),我试图确保它是不是偶然工作的。
struct Node
{
int value;
std::array<Node *, 100> children;
}
更新:
这里的指针是垃圾:
struct Node
{
int value;
std::array<Node *, 100> children;
}
struct Node
{
Node() : children() {}
int value;
std::array<Node *, 100> children;
}
这里的指针是nullptr:
struct Node
{
int value;
std::array<Node *, 100> children {};
}
struct Node
{
Node() : children{} {}
int value;
std::array<Node *, 100> children;
}
如有错误请指正
在指针被赋值之前,它默认指向一个"garbage"地址。编译器不会为它们分配默认值 nullptr
。事实上,它不会为指针分配任何 "default" 值。
编辑:
来自 cppreference documentation for std::array:
note that default initialization may result in indeterminate values for non-class T
所以如果使用默认构造函数,需要自己给每个元素赋值nullptr
。
在std::array
的构造函数中引用cppreference:
initializes the array following the rules of aggregate initialization
(note that default initialization may result in indeterminate values
for non-class T)
通过像 std::array<Node *, 100> children;
那样声明您的变量,您可以调用默认构造函数。并且,根据初始化规则,PODs(int
、char
、double
、指针、...)不会被默认初始化。所以不,如果你不使用聚合初始化,你的数组将不会用 nullptr
初始化。
聚合初始化
std::array<Node *, 100> children;
调用默认构造函数,但没有给出聚合初始化器,因此聚合初始化不会发生。然而
std::array<Node *, 100> children{}
std::array<Node *, 100> children = {};
不仅会调用默认构造函数,还会进行聚合初始化。在这种情况下,聚合 {}
只是空的。并且,遵循聚合初始化规则,如果初始化器少于数据成员,则每个未初始化的成员都将被默认初始化。所以
Node x;
std::array<Node *, 100> children = {&x};
例如,将使用指向 x
的指针初始化第一个数组元素,每个后续元素将默认初始化为 nullptr
.
根据this answer,std::array
指针的默认初始化将不会初始化它包含的指针,它们的值将是不确定的。
std::array<Node *, 100> children; // pointers are uninitialized
然而,您可以使用 value 初始化将所有包含的指针初始化为 nullptr
。在 std::array
上,这具有对数组中的每个值进行值初始化的效果,进而对每个指针进行零初始化。
std::array<Node *, 100> children {}; // pointers are all null
在成员初始化列表中,你也可以这样做:
Node::Node() : children{/* value init array */} {/* empty c'tor body */}
给定下面的代码是否正确,编译器应该生成 Node()
,它应该调用 std::array<Node *, 100>()
,它应该将所有 100 个指针初始化为 nullptr。
旁注:我知道如果我使用 std::array<Node *, 100> children {};
,我可以做到这一点,但我并没有试图让我的代码工作(它已经工作),我试图确保它是不是偶然工作的。
struct Node
{
int value;
std::array<Node *, 100> children;
}
更新:
这里的指针是垃圾:
struct Node
{
int value;
std::array<Node *, 100> children;
}
struct Node
{
Node() : children() {}
int value;
std::array<Node *, 100> children;
}
这里的指针是nullptr:
struct Node
{
int value;
std::array<Node *, 100> children {};
}
struct Node
{
Node() : children{} {}
int value;
std::array<Node *, 100> children;
}
如有错误请指正
在指针被赋值之前,它默认指向一个"garbage"地址。编译器不会为它们分配默认值 nullptr
。事实上,它不会为指针分配任何 "default" 值。
编辑:
来自 cppreference documentation for std::array:
note that default initialization may result in indeterminate values for non-class T
所以如果使用默认构造函数,需要自己给每个元素赋值nullptr
。
在std::array
的构造函数中引用cppreference:
initializes the array following the rules of aggregate initialization (note that default initialization may result in indeterminate values for non-class T)
通过像 std::array<Node *, 100> children;
那样声明您的变量,您可以调用默认构造函数。并且,根据初始化规则,PODs(int
、char
、double
、指针、...)不会被默认初始化。所以不,如果你不使用聚合初始化,你的数组将不会用 nullptr
初始化。
聚合初始化
std::array<Node *, 100> children;
调用默认构造函数,但没有给出聚合初始化器,因此聚合初始化不会发生。然而
std::array<Node *, 100> children{}
std::array<Node *, 100> children = {};
不仅会调用默认构造函数,还会进行聚合初始化。在这种情况下,聚合 {}
只是空的。并且,遵循聚合初始化规则,如果初始化器少于数据成员,则每个未初始化的成员都将被默认初始化。所以
Node x;
std::array<Node *, 100> children = {&x};
例如,将使用指向 x
的指针初始化第一个数组元素,每个后续元素将默认初始化为 nullptr
.
根据this answer,std::array
指针的默认初始化将不会初始化它包含的指针,它们的值将是不确定的。
std::array<Node *, 100> children; // pointers are uninitialized
然而,您可以使用 value 初始化将所有包含的指针初始化为 nullptr
。在 std::array
上,这具有对数组中的每个值进行值初始化的效果,进而对每个指针进行零初始化。
std::array<Node *, 100> children {}; // pointers are all null
在成员初始化列表中,你也可以这样做:
Node::Node() : children{/* value init array */} {/* empty c'tor body */}