C ++ std :: variant vs std :: any

mas*_*oud 5 c++ c++17

C ++ 17呈现std::variantstd::any,都能够在对象下存储不同类型的值。对我来说,它们在某种程度上是相似的(是吗?)。

除此以外,还std::variant限制了条目类型。为什么我们应该更喜欢std::variantstd::any这简单的使用?

Yak*_*ont 14

编译时检查的内容越多,运行时错误的数量就越少。

variant保证它包含类型列表之一(加上无值的异常)。它为您提供了一种方法,以确保在其上运行的代码考虑带有std::visit; 的变体中的每种情况。甚至每对都variants(或更多)。

any才不是。随着any你能做的最好的是“如果类型不完全是我要求的,一些代码将无法运行”。

variant存在于自动存储中。 any可以使用免费商店;这种方法any具有的性能和noexcept(false)该问题variant没有。

检查-中的N个类型中的哪一个是O(N),any因为variant它是O(1)。

any是一个打扮void*variant是一个打扮union

any无法存储不可复制或不可移动的类型。 variant能够。

类型variant是供您的代码读者阅读的文档。

传递variant<Msg1, Msg2, Msg3>通过API使操作明显; 通过any那里意味着了解API需要可靠的文档或阅读实现源。

任何对静态无类型语言感到沮丧的人都将理解的危险any

现在,这并不意味着any不好;它不能解决与相同的问题variant。作为用于类型擦除目的的可复制对象,它可能很棒。运行时动态类型具有它的位置;但是那个地方不是“无处不在”,而是“无法避免的地方”。

  • 一句话很好的解释:“任何都是一个盛装的虚空*。变体是一个盛装的联合”。 (12认同)

t.n*_*ese 8

不同之处在于对象存储在由std::variant以下分配的内存中:

cppreference.com - std::variant

与联合一样,如果一个变体持有某个对象类型的值T则 的对象表示T直接在变体本身的对象表示中分配。不允许 Variant 分配额外的(动态)内存

并且std::any这是不可能的。

至于 a std::variant, 只需要为它std::variant自己分配一个内存,它可以留在堆栈上。


Hol*_*Cat 5

除了从不使用额外的堆内存之外,variant还有另一个优点:

你可以std::visit一个variant,但不是any