1

考虑:

class x {
    std::array<int, 4> data_;

public:
    x() /*no reference to data_ here*/ {}
};

中的int元素是否data_归零,或者它们的值是不确定的?

通过扩展,在这种情况下也是如此:

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 */);
    }
};
4

1 回答 1

3

std::array文档中,在构造函数部分,我们可以阅读:

按照聚合初始化规则初始化数组(请注意,默认初始化可能导致非类 T 的值不确定

强调我的

在您的情况下,您有一个std::array<int, 4>. int匹配非类类型的定义,因此默认初始化将使data_成员内容具有不确定的值。

如果您已将data_成员初始化为:

std::array<int, 4> data_ {}; // Note the braces

元素将被值初始化,这将导致int元素的零初始化。


编辑(来自评论):

std::variant::emplace()转发其参数,但由于您没有为 emplaced 提供任何参数,因此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;
于 2020-02-26T12:44:12.470 回答