Может ли объединение содержать объекты класса с конструктором, определяемым пользователем?

Может ли объединение содержать объекты класса с конструктором, определяемым пользователем? Когда я пытаюсь создать, он выдает сообщение об ошибке: «Член 'c::aa' союза 'c' имеет определяемый пользователем конструктор или нетривиальный конструктор по умолчанию». Это стандарт или есть какая-то ошибка в моем коде?

Код, который я тестировал,

class a
{  
public:

  int aaa;
  a(){}

};

class b
{

public :

  long bbb;
  b() { }

};

union c
{

public :

  c()  {}

    a aa;
  b bb;  
};

person GAP    schedule 09.01.2014    source источник


Ответы (3)


До C++11 ответ был «нет» — union может содержать только типы значений (если заимствовать термин из управляемого кода), то есть тип, который содержит только элементы данных.

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

Возможно, вы хотите struct.

person Brian A. Henning    schedule 09.01.2014
comment
Спасибо за ответ. Я использовал класс для целей обучения. Итак, является ли использование объектов класса плохой практикой или это проблема, которая может привести к сбою/неоднозначному поведению? - person GAP; 09.01.2014
comment
Я бы назвал это плохой практикой. Используйте только union, когда вы явно хотите, чтобы два объекта использовали одно и то же пространство памяти. В девяти случаях из десяти вы почти всегда должны использовать struct, а не union. - person Brian A. Henning; 09.01.2014
comment
При каких обстоятельствах this хранится в памяти объекта? - person Rob Kennedy; 09.01.2014
comment
Неважно, используете ли вы класс или структуру. Структура также может иметь конструктор. Честно говоря, я немного удивлен, что конструктор может быть проблемой, поскольку это не делает структуру памяти нетривиальной. Я думал, что С++ 11 должен ослабить это правило. - person shawn1874; 10.01.2014

Это возможно, начиная с С++ 11 ("неограниченные объединения").

person Kerrek SB    schedule 09.01.2014
comment
Еще один богатый источник умопомрачительного кода. это не нарушит какой-либо код, поскольку это только ослабит существующее правило. Что касается разрешения писать новое сломанное программное обеспечение, держу пари, что так и будет. Великолепная новая площадка для фанатов шаблонов, без сомнения :). - person kuroi neko; 09.01.2014
comment
@kuroi - я не понимаю твоего комментария. Конечно, это не сломает существующий код. С чего бы это? Что заставляет вас думать, что написание совершенно нового сломанного кода допустимо? - person shawn1874; 10.01.2014
comment
Я имею в виду, что ребята из C++11 слишком много говорят, так как мы можем это сделать, давайте просто сделаем это на мой вкус. Таким образом, теперь вы можете назначить одного привилегированного члена, которому будет разрешено портить содержимое всех его братьев и сестер. Несомненно, компьютерные гении извлекут из этого максимальную пользу, но я иногда задаюсь вопросом, перевесят ли преимущества огромное количество ошибок, вызванных простыми смертными, непреднамеренно блуждающими по этим девственным землям. Но это всего лишь праздная мысль. Я больше не зарабатываю на жизнь C++. - person kuroi neko; 10.01.2014
comment
Нет, в данном случае они просто исправляют ошибку, которая никогда не должна была быть частью более ранних стандартов, как уже указал Бьярн. Никогда не было веской причины для предотвращения использования классов с тривиальными функциями в объединениях. Извините, но я немного не понимаю, почему вы думаете, что это плохо. Я думаю, это фантастика. Почему я не должен иметь тривиальные функции для классов/структур внутри союза? Мне кажется полезным. - person shawn1874; 10.01.2014

class a
{  
public:

  int aaa;
  a(){}

};

class b
{

public :

  long bbb;
  b() { }

};

union c
{

public :

  c()  {}

    a aa;
  b bb;  
};

int main()
{
    return 0;
}

Приведенный выше код отлично работал с использованием следующего онлайн-компилятора. http://www.compileonline.com/compile_cpp11_online.php

Так что ответ да и нет, в зависимости от вашего компилятора. MS VS 2010 не компилирует этот код, потому что он еще не полностью соответствует C++11. Очевидно, что последний компилятор C++11 GCC прекрасно его скомпилирует! На мой взгляд, это здорово, потому что все время тривиальный пользовательский конструктор просто инициализирует данные и не меняет структуру памяти.

В стандарте C++ 03 указано, что любой класс или структура с конструктором, определяемым пользователем, не является POD. Бьярн Страуструп написал что-то об этом на своей домашней странице, указав, что это слишком строгое определение для POD по сравнению с не-POD, потому что определяемые пользователем функции не всегда вызывают нетривиальное расположение памяти. Поэтому правило было смягчено.

person shawn1874    schedule 09.01.2014