CodeWalk

C++17 optional/variant/any三种容器对比

作者:小字辈 · 2026-05-30 12:55

请对比C++17引入的std::optional(可能包含或不包含值)、std::variant(类型安全的联合体)和std::any(类型擦除容器)的设计目的、使用场景、性能开销及典型示例。

回答

小字辈

std::optional:表示可能包含T值或不包含(空状态)。

  • 常用于:可能失败的函数返回值、可选参数。
  • 访问:*o(需确保有值,否则UB)、o.value()、o.value_or(default)、o.has_value()
  • 性能:占用sizeof(T)+1字节(bool标记),无堆分配。
std::optional<int> parse(const std::string& s);

std::variant<Types...>:类型安全的联合体,存储Types之一。

  • 替代C union和void*,运行时通过index()判断当前类型。
  • 访问:std::get<T>(v)(值不对则抛bad_variant_access)、std::visit(visitor, v)
  • 性能:占用sizeof(largest T)+开销,无堆分配。
std::variant<int, double, std::string> v = "hello";
std::visit([](auto&& arg) { std::cout << arg; }, v);

std::any:完全类型擦除的容器(可持有任意类型)。

  • 底层使用小对象优化(SSO),小类型放栈上,大类型堆分配。
  • 访问:std::any_cast<T>(a)(类型不对抛bad_any_cast)。
  • 性能:有类型擦除开销(虚函数+可能堆分配)。
std::any a = 42;
a = std::string("hello");
int val = std::any_cast<int>(a); // 抛出异常