Недавно я обнаружил, что вы не можете иметь одновременно инициализацию классов и список инициализаторов.
Сбой следующего кода:
struct s
{
int i=0;
};
int main() {
s s1; //s1.i = 0
//s s2={42}; //fails
return 0;
}
Если я удаляю инициализацию класса in, список инициализаторов работает нормально!
Может кто-нибудь объяснить мне, почему такая вещь не допускается?
На самом деле это разрешено в C ++ 14.
struct s
{
int i=0;
};
int main() {
s s1;
s s2 = {42}; // succeeds
}
Вероятно, ваш компилятор просто не реализует новое правило в C ++ 14. Однако последняя версия clang принимает это и делает все правильно в режиме C ++ 14.
Когда в C ++ 11 была добавлена инициализация в классе, она была указана так, что она не позволяла классу быть агрегатом. Это было сделано потому, что в то время концепция агрегирования была тесно связана с типами PoD, которые должны быть легко конструируемыми. Наличие инициализации в классе означает, что тип больше не является тривиально конструируемым. Однако с тех пор эти две концепции стали более независимыми, и поэтому для C ++ 14 было принято короткое предложение, отменяющее это решение.
Эта инициализация:
s s1 = { 42 };
требует, чтобы s
быть совокупный, или что у него есть действительный конструктор, например, int или std::initializer_list
,
Когда вы добавляете инициализацию члена в точке объявления, вы отображаете свой класс s
неагрегированный, поэтому вы больше не можете использовать агрегатную инициализацию.
Вы можете использовать ту же инициализацию синтаксис для вашего неагрегата, добавив конструктор:
struct s
{
s(int i) : i(i) {}
int i=0;
};
Я считаю, что это ограничение было смягчено для C ++ 14.
Увидеть Что такое агрегаты … для дополнительной информации.