Почему структура, которая имеет другую структуру, заключенную в объединение как член, не компилируется без явного конструктора по умолчанию? - PullRequest
0 голосов
/ 04 ноября 2018

Это отношения, о которых я говорю:

struct A{
    int i = 1;
};

struct B{
    union{A a;};
};

void main(){
    B b;
};

В этом созвездии мой компилятор (vs2015) жалуется на удаление конструктора по умолчанию B B::B(void) с замечанием, что компилятор сгенерировал B::B:

../test.cpp(155): error C2280: "B::B(void)" : Es wurde versucht, auf eine gelöschte Funktion zu verweisen
../test.cpp(152): note: Compiler hat hier "B::B" generiert

(извините, я не смог убедить MSVC говорить со мной по-английски)

Любое из этих двух изменений кода исправляет это:

struct A{
    int i; //removed initialzation of member to 1
};

или

struct B{
    B(){} //adding explicit default constructor
    union{A a;};
};

Я знаю, что добавление конструктора по умолчанию, который ничего не делает, не совсем сложный или раздражающий обходной путь, но я действительно хочу знать, почему C ++ заставляет меня это делать.

1 Ответ

0 голосов
/ 04 ноября 2018

Это из-за [class.default.ctor] p2 , который говорит:

По умолчанию конструктор по умолчанию для класса X определяется как удаленный, если:

  • (2.1) X - это объединение, в котором есть вариантный член с нетривиальным конструктором по умолчанию, и ни у одного вариантного члена X нет инициализатора элемента по умолчанию,

.....

и мы можем понять, почему A не имеет тривиального конструктора по умолчанию из [class.default.ctor] p3 , который говорит:

Конструктор по умолчанию тривиален, если он не предоставлен пользователем и если:
- (3.1) - в его классе нет виртуальных функций (10.6.2) и нет виртуальных базовые классы (10.6.1) и
- (3.2) - нет нестатического члена данных его класс имеет инициализатор члена по умолчанию (10.3) и
- (3.3) - все прямые базовые классы этого класса имеют тривиальные конструкторы по умолчанию, и
- (3.4) - для всех нестатических данных-членов своего класса, которые типа класса (или его массив), каждый такой класс имеет тривиальный конструктор по умолчанию.

Мы можем видеть из этот живой пример с божьей стрелой что удаление инициализатора нестатического члена делает программу правильно сформированной.

struct A{
    int i ; // no NSDMI
};

struct B{
    union{A a;};
};

Бумага, которая привела к формулировке, которую мы имеем сегодня: n2544: 1 Неограниченные Союзы (Редакция 2) , здесь рассматриваются рациональные:

Мы также изменили способ неявно объявленного специального функции-члены союзов генерируются в следующем способ: если нетривиальная специальная функция-член определена для любой член профсоюза или член анонимного союза внутри класс, эта специальная функция-член будет неявно удалена (8.4 ¶10) для союза или класса. Это мешает компилятору пытаться написать код, который он не может знать, как писать, и заставляет программист, чтобы написать этот код, если это необходимо. Тот факт, что компилятор не может написать такую ​​функцию, это не причина, чтобы программист делает это.

Объединение имеет только один активный член, если один или несколько членов не могут быть созданы по умолчанию, как компилятору выбрать, какой из них сделать активным по умолчанию?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...