介绍了 C++17 引入的 std::any。它是一个可以存储绝对任何类型变量的容器(本质上是一个类型安全的 void*),但与 void* 不同的是,它会处理对象的构造和析构。 []

1. 基本用法 []#

  • 包含头文件#include <any>
  • 赋值:你可以随意给它赋值,不需要预先定义类型。

2. 如何提取数据:std::any_cast []#

由于 any 可以是任何东西,你必须使用 std::any_cast 并指定类型来取回数据:

  • 按值取回std::any_cast<int>(data)。如果类型不匹配,会抛出 std::bad_any_cast 异常。 []
  • 按引用取回:为了性能,通常建议取引用或指针,避免拷贝。 []

3. 工作原理与性能开销 []#

这是本集的重点,Cherno 解释了为什么不能滥用 std::any

  • 动态内存分配(Heap Allocation):对于较大的类型,std::any 会在堆上分配内存。这意味着它比直接使用类型或 std::variant 要慢得多。 []
  • SBO(小对象优化):对于像 int 这样的小类型,any 通常会直接存在变量内部(栈上),不触发堆分配,但这取决于编译器实现。 []
  • 类型安全:它内部存储了类型信息,所以它知道你存的是什么,并能在运行时进行类型检查。 []

4. std::any vs std::variant []#

Cherno 强调了两者最本质的区别:

  • std::variant类型安全且高效。你必须列出所有类型,它在编译时就确定了空间,通常在栈上,性能接近原生类型。 []
  • std::any更灵活但更慢。它不要求你列出类型,但在提取数据时有运行时开销(类型检查和潜在的堆内存解引用)。 []

5. 什么时候该用它? []#

  • 当你真的完全不知道会接收到什么类型的数据时(例如编写极其通用的插件系统或反射系统)。
  • 如果你知道可能的几种类型,永远优先使用 std::variant。 []

总结提示: std::any 就像是一个“终极容器”,它虽然强大,但由于性能损耗(堆分配和运行时转换),在高性能 C++ 开发中应谨慎使用。