【问题标题】:C++ std::variant vs std::anyC++ std::variant vs std::any
【发布时间】:2019-10-11 17:21:37
【问题描述】:

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

除此之外,std::variant 还限制条目类型。为什么我们应该更喜欢std::variant 而不是更易于使用的std::any

【问题讨论】:

  • std::variant 只适用于一组预定义的类型,而std::any 字面上适用于任何类型。这完全取决于您的用例,哪个是更好的选择。
  • @πάνταῥεῖ:什么是预定义的类型集
  • 粗略地说,第一个是编译时,第二个是运行时。
  • 没有std::visit() for std::any;恕我直言,这应该是在可能的情况下更喜欢std::variant 的正当理由。
  • 这就像 void* 与联合 imo 的对比

标签: c++ c++17


【解决方案1】:

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

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

any 没有。使用any,您能做的最好的事情就是“如果类型不是我所要求的,某些代码将无法运行”。

variant 存在于自动存储中。 any可以使用免费商店;这意味着any 有性能,而noexcept(false)variant 没有的问题。

对于any,检查其中 N 个类型中的哪一个是 O(N) —— 对于 variant,它是 O(1)。

any 是盛装的void*variant 是盛装打扮的union

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

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

通过 API 传递variant<Msg1, Msg2, Msg3> 使操作显而易见;传递any 意味着理解 API 需要可靠的文档或阅读实现源代码。

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

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

【讨论】:

  • 一句话很好的解释:“任何都是装扮的虚空*。变体是装扮的联合”。
【解决方案2】:

不同的是对象存储在std::variant分配的内存中:

cppreference.com - std::variant

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

对于std::any,这是不可能的。

到目前为止,std::variant 只需要为std::variant 本身分配一个内存,并且它可以留在堆栈上。

【讨论】:

    【解决方案3】:

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

    您可以std::visitvariant,但不能any

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 1970-01-01
      相关资源
      最近更新 更多