介绍了 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++ 开发中应谨慎使用。