C++14 равномерная инициализация на неагрегате
Я использую Visual C++ 2013. Когда класс является агрегатом, он инициализируется нулями. Когда он не агрегатный, он инициализируется по умолчанию и остается неопределенным. Это почему?
#include <iostream>
using namespace std;
class Test_1
{
public:
int i;
void f(){};
};
class Test_2
{
public:
int i;
virtual void f(){};
};
int main()
{
Test_1 t1{};
Test_2 t2{};
cout<<t1.i<<endl; //0
cout<<t2.i<<endl; //-858993460
getchar();
}
1 ответ
Решение
Если ваш компилятор делает это, он сломан.
[dcl.init.list] / p3 (все цитаты взяты из N4140):
Инициализация списка объекта или ссылки типа
T
определяется следующим образом:
- Если
T
является агрегатом, выполняется агрегатная инициализация (8.5.1).- В противном случае, если список инициализатора не имеет элементов и
T
тип класса с конструктором по умолчанию, объект инициализируется значением- [...]
[Dcl.init]/ P8:
Инициализировать значение объекта типа
T
средства:
- если
T
является (возможно, cv-квалифицированным) типом класса (раздел 9) без конструктора по умолчанию (12.1) или конструктора по умолчанию, предоставленного или удаленного пользователем, тогда объект инициализируется по умолчанию;- если
T
является (возможно, cv-квалифицированным) типом класса без предоставленного пользователем или удаленного конструктора по умолчанию, тогда объект инициализируется нулями, и проверяются семантические ограничения для инициализации по умолчанию, и если T имеет нетривиальный конструктор по умолчанию, объект инициализируется по умолчанию;- если T является типом массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулями.
Test_2
это не совокупность, поэтому t2
должен был быть инициализирован значением. В свою очередь, так как Test_2
конструктор по умолчанию не предоставляется пользователем, t2
должен быть сначала инициализирован нулем (вызывая t2.i
для инициализации в 0), а затем запускается конструктор по умолчанию.