将 `std::array<int, N>` 中的元素作为 class 成员进行默认初始化
Do elements in `std::array<int, N>` as a class member get default intialised
考虑:
class x {
std::array<int, 4> data_;
public:
x() /*no reference to data_ here*/ {}
};
data_
中的 int
元素是否归零,或者它们的值是否不确定?
推而广之,在这种情况下也是如此:
class x {
std::variant<std::array<int, 4> /*other stuff here*/> data_;
public:
x() /*no reference to data here*/ {
data_.emplace<std::array<int, 4>>(/* no args */);
}
};
编辑:
扩展:有没有一种方法可以从变体中获得所需的行为(不初始化数据)。
如果我将这两个示例配对在一起,我应该能够做到:
struct no_init_array {
std::array<int, 4> array;
no_init_array() { } //does nothing
};
class x {
std::variant<no_init_array/*other stuff here*/> data_;
public:
x() /*no reference to data here*/ {
//call default ctor of no_init_array
//which does not init the std::array (I hope)
data_.emplace<no_init_array>(/* no args */);
}
};
从std::array
documentation,在构造函数部分,我们可以读到:
initializes the array following the rules of aggregate initialization (note that default initialization may result in indeterminate values for non-class T)
强调我的
在你的例子中,你有一个 std::array<int, 4>
。 int
匹配非 class 类型的定义,因此默认初始化将使 data_
成员内容具有不确定的值。
如果您将 data_
成员初始化为:
std::array<int, 4> data_ {}; // Note the braces
元素将被值初始化,这将导致 int
个元素的零初始化。
编辑(来自评论):
std::variant::emplace()
转发其参数,但由于您没有为放置的 std::array<int, 4>
提供任何参数,您的 std::variant
将保存一个值初始化的 std::array<int, 4>
,因此基础 int
元素将被零初始化。
既然您想要第二个用例并且您希望数组内容保持未初始化状态,您当然可以按照您的建议进行操作:
struct X
{
std::array<int, 4> data_;
X()
{}
};
struct Y
{
std::variant<X, /*...*/> data_ {};
Y()
{
data_.emplace<X>();
}
};
但您需要注意,在稍后正确初始化之前,数组内容不会被意外访问。
编辑:
之后要初始化 std::array
,您应该确保它是通过引用而不是数组的副本执行的(为了避免通过复制未初始化的数据发生未定义的行为)。
例如:
Y y;
//X x = std::get<X>(y); // Wrong
X & x = std::get<X>(y); // Right
x.data_[0] = 42;
x.data_[1] = 422;
x.data_[2] = 442;
x.data_[3] = 4422;
考虑:
class x {
std::array<int, 4> data_;
public:
x() /*no reference to data_ here*/ {}
};
data_
中的 int
元素是否归零,或者它们的值是否不确定?
推而广之,在这种情况下也是如此:
class x {
std::variant<std::array<int, 4> /*other stuff here*/> data_;
public:
x() /*no reference to data here*/ {
data_.emplace<std::array<int, 4>>(/* no args */);
}
};
编辑:
扩展:有没有一种方法可以从变体中获得所需的行为(不初始化数据)。
如果我将这两个示例配对在一起,我应该能够做到:
struct no_init_array {
std::array<int, 4> array;
no_init_array() { } //does nothing
};
class x {
std::variant<no_init_array/*other stuff here*/> data_;
public:
x() /*no reference to data here*/ {
//call default ctor of no_init_array
//which does not init the std::array (I hope)
data_.emplace<no_init_array>(/* no args */);
}
};
从std::array
documentation,在构造函数部分,我们可以读到:
initializes the array following the rules of aggregate initialization (note that default initialization may result in indeterminate values for non-class T)
强调我的
在你的例子中,你有一个 std::array<int, 4>
。 int
匹配非 class 类型的定义,因此默认初始化将使 data_
成员内容具有不确定的值。
如果您将 data_
成员初始化为:
std::array<int, 4> data_ {}; // Note the braces
元素将被值初始化,这将导致 int
个元素的零初始化。
编辑(来自评论):
std::variant::emplace()
转发其参数,但由于您没有为放置的 std::array<int, 4>
提供任何参数,您的 std::variant
将保存一个值初始化的 std::array<int, 4>
,因此基础 int
元素将被零初始化。
既然您想要第二个用例并且您希望数组内容保持未初始化状态,您当然可以按照您的建议进行操作:
struct X
{
std::array<int, 4> data_;
X()
{}
};
struct Y
{
std::variant<X, /*...*/> data_ {};
Y()
{
data_.emplace<X>();
}
};
但您需要注意,在稍后正确初始化之前,数组内容不会被意外访问。
编辑:
之后要初始化 std::array
,您应该确保它是通过引用而不是数组的副本执行的(为了避免通过复制未初始化的数据发生未定义的行为)。
例如:
Y y;
//X x = std::get<X>(y); // Wrong
X & x = std::get<X>(y); // Right
x.data_[0] = 42;
x.data_[1] = 422;
x.data_[2] = 442;
x.data_[3] = 4422;