Из документации std::array
в разделе конструктора мы можем прочитать:
инициализирует массив в соответствии с правилами агрегированная инициализация ( обратите внимание, что инициализация по умолчанию может привести к неопределенным значениям для некласса T )
выделение шахты
В вашем случае вы имеете std::array<int, 4>
. int
соответствует определению неклассного типа, поэтому при инициализации по умолчанию содержимое элемента 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;