Подтвердить что ты не робот

Можно ли объединить несколько объектов внутри союза?

Что делать, если у меня есть это:

union{
    vector<int> intVec ;
    vector<float> floatVec ;
    vector<double> doubleVec ;
} ;

Конечно, я буду использовать только один из трех векторов. Но... что происходит, когда все 3 вектора конструируются?
Могут ли сборщики трех векторов вмешиваться друг в друга? (поскольку 3 из них находятся в одном адресе памяти)

Спасибо.

4b9b3361

Ответ 1

Существующий стандарт С++ не допускает не-POD-типы внутри союзов. Вы получите эту ошибку компилятора от gcc:

error: member ‘std::vector<int, std::allocator<int> >
<anonymous union>::i’ with constructor not allowed in union
error: member ‘std::vector<int, std::allocator<int> >
<anonymous union>::i’ with destructor not allowed in union

Новый стандарт С++ (С++ 0x) предлагает неограниченные объединения, но добавляет еще больше ошибок в жизни объекта на С++.

Ответ 2

У вас не может быть объединений, содержащих не классы POD. Ваш образец не скомпилируется.

Вы можете использовать boost::variant как безопасную альтернативу профсоюзам C. Смотрите документацию на boost.org. Однако вы можете пересмотреть свой дизайн и использовать вместо этого полиморфизм. Конечно, зависит от того, что вы пытаетесь достичь.

Ответ 3

Из стандарта С++, раздел 9.5:

Объект класса с нетривиальный конструктор (12.1), a нетривиальный конструктор копирования (12.8), a нетривиальный деструктор (12.4) или нетривиальный оператор присваивания копии (13.5.3, 12.8) не может быть членом союз,

Здесь для "нетривиального" чтения "полезно": -)

Ответ 4

Не могли бы ли сборщики трех векторов вмешиваться друг в друга? (поскольку 3 из них находятся в одном адресе памяти)

Стандарт С++ не позволяет вашей программе, поэтому он (в лучшем случае!) определяет реализацию, что происходит.

Если, скажем, ваша реализация вызывает все три конструктора по умолчанию, и все они хранят память, и сохраняет указатель на вновь выделенное пространство, у вас есть утечка памяти (первые два распределения перезаписываются третьим).

Если все деструкторы вызываются и все они освобождают "свою" память, вы будете делать двойную свободную (тройную, обычную); это, вероятно, приведет к повреждению структуры данных распределения, что является плохим веществом. Будьте счастливы, если вы потерпите крах, потому что отлаживать их гораздо сложнее, если вы этого не сделаете.

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

(Более чувствительная вещь может состоять только в построении по умолчанию первого класса, но это все еще не чувствительно, а просто менее сумасшедшее...)

Ответ 5

Возможно, вы захотите посмотреть Boost.Variant, который может содержать одно значение различных типов.

Ответ 6

Теперь C++ стандарт поддерживает вариант. Проверьте https://en.cppreference.com/w/cpp/utility/variant.

std::variant

Определено в заголовке

template <class... Types>   
class variant;

(since C++17)

Шаблон класса std::variant представляет объединение с безопасным типом. Экземпляр std::variant в любой момент времени либо содержит значение одного из его альтернативных типов, либо в случае ошибки - нет значения (это состояние трудно достичь, см. valueless_by_exception).

Как и в случае союзов, если вариант содержит значение некоторого типа объекта T, объектное представление T выделяется непосредственно в объектном представлении самого варианта. Варианту запрещено выделять дополнительную (динамическую) память.

Вариант не может содержать ссылки, массивы или тип void. Пустые варианты также плохо сформированы (вместо них можно использовать std::variant<std::monostate>).

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

В соответствии с поведением объединений во время агрегатной инициализации вариант, созданный по умолчанию, содержит значение своей первой альтернативы, если только эта альтернатива не является конструируемой по умолчанию (в этом случае вариант также не конструируется по умолчанию), Вспомогательный класс std::monostate можно использовать для создания таких вариантов по умолчанию.