Пожалуйста, объясните, в чем разница между union
и std::variant
и почему std::variant
был введен в стандарт? В каких ситуациях мы должны использовать std::variant
для старой школы union
?
Где использовать std:: variant over union?
Ответ 1
Вообще говоря, вы должны предпочесть variant
, если не появится одно из следующих:
-
Вы обманываете. Вы делаете пиратство или другие вещи, которые являются UB, но вы надеетесь, что ваш компилятор не нарушит ваш код.
-
Вы выполняете некоторые псевдо-пунниры, разрешенные С++
union
: преобразование между совместимыми с макетами типами или между общими начальными последовательностями. -
Вам явно нужна тривиальная совместимость и/или совместимость макетов.
variant<Ts>
не требуется, чтобы какой-либо конкретный макет или тривиальная копируемость.unions
стандартных типов макета - стандартная компоновка, аunion
тривиально-скопируемых типов тривиально можно копировать.Обратите внимание, что существует предложение сделать
variant
тривиально скопируемое, если его типы компонентов тривиально копируются. Он предложил в качестве отчета о дефектах против С++ 17, поэтому это поведение будет эффективно передано в С++ 17. -
Вам нужна низкоуровневая поддержка для переключения объектов на месте. Использование буфера памяти для таких вещей не дает тривиальных гарантий копирования, которые вы могли бы получить из
union
.
Основное различие между ними состоит в том, что variant
знает, какой тип он хранит, а union
ожидает, что вы будете отслеживать это извне. Поэтому, если вы попытаетесь получить доступ к неправильному элементу в variant
, вы получите исключение или nullptr
. В отличие от этого, при использовании union
это просто поведение undefined.
union
- инструмент нижнего уровня, поэтому его следует использовать только тогда, когда вам абсолютно необходим этот уровень ниже.
variant
также имеет механизм для посещения, а это означает, что вы избегаете наличия кучи операторов if
, где вы спрашиваете "если это тип X, сделайте это. Если это тип Y, сделайте это и т.д.".