在哪里使用 std::variant 而不是 union?
Where to use std::variant over union?
请解释一下 union
和 std::variant
之间的区别以及为什么将 std::variant
引入标准?在什么情况下我们应该使用 std::variant
而不是老式的 union
?
一般来说,除非出现以下情况之一,否则您应该更喜欢 variant
:
你在作弊。您正在做 type-punning 或其他 UB 的事情,但您希望您的编译器不会破坏您的代码。
您正在做 C++ union
允许做的一些 pseudo-punnery:layout-compatible 类型之间或公共初始序列之间的转换。
您明确需要布局兼容性。 variant<Ts>
不需要有任何特定的布局; unions
个标准布局类型是标准布局。
您需要 low-level 支持 in-place 对象切换。为这些事情使用内存缓冲区并不能提供你可以摆脱 union
.
的简单复制保证。
两者之间的基本区别在于 variant
知道 它存储的是哪种类型,而 union
希望您从外部跟踪它。因此,如果您尝试访问 variant
中的错误项目,您将得到一个异常或 nullptr
。相比之下,使用 union
这样做只是未定义的行为。
union
是一个 lower-level 工具,因此只应在绝对需要 lower-level.
时使用
variant
也有进行访问的机制,这意味着您可以避免出现一堆 if
语句,您可以在其中询问“如果它是类型 X,请执行此操作。如果它是类型Y,做那个,等等"。
请解释一下 union
和 std::variant
之间的区别以及为什么将 std::variant
引入标准?在什么情况下我们应该使用 std::variant
而不是老式的 union
?
一般来说,除非出现以下情况之一,否则您应该更喜欢 variant
:
你在作弊。您正在做 type-punning 或其他 UB 的事情,但您希望您的编译器不会破坏您的代码。
您正在做 C++
union
允许做的一些 pseudo-punnery:layout-compatible 类型之间或公共初始序列之间的转换。您明确需要布局兼容性。
variant<Ts>
不需要有任何特定的布局;unions
个标准布局类型是标准布局。您需要 low-level 支持 in-place 对象切换。为这些事情使用内存缓冲区并不能提供你可以摆脱
的简单复制保证。union
.
两者之间的基本区别在于 variant
知道 它存储的是哪种类型,而 union
希望您从外部跟踪它。因此,如果您尝试访问 variant
中的错误项目,您将得到一个异常或 nullptr
。相比之下,使用 union
这样做只是未定义的行为。
union
是一个 lower-level 工具,因此只应在绝对需要 lower-level.
variant
也有进行访问的机制,这意味着您可以避免出现一堆 if
语句,您可以在其中询问“如果它是类型 X,请执行此操作。如果它是类型Y,做那个,等等"。