std::variant是C++17提供的类型安全多类型存储方案,相比union和基类指针,它在编译期确定所有可能类型,避免运行时类型错误。它通过std::get、std::holds_alternative和std::visit等机制实现安全访问,其中std::visit结合lambda可优雅处理多类型逻辑,避免if-else链。与union相比,std::variant支持复杂类型且无未定义行为;与基类指针相比,它无虚函数开销、无需堆分配,性能更高。实际使用中需注意默认构造问题,若首类型无默认构造函数,应将std::monostate置于首位以确保可构造性。

说起C++里多类型存储,很多老手可能首先想到
union
std::variant
刚接触
std::variant
std::tuple
std::variant<int, double, std::string> myValue;
int
double
std::string
int
myValue = 42;
myValue = 3.14;
myValue = "Hello, Variant!";
那么怎么把值取出来呢?这是关键。
std::get
std::get<int>(myValue)
std::get<0>(myValue)
double
std::get<int>
std::bad_variant_access
union
为了避免这种异常,你可以先用
std::holds_alternative<int>(myValue)
int
std::visit
std::visit
variant
variant
if-else if
立即学习“C++免费学习笔记(深入)”;
看个简单的
std::visit
#include <variant>
#include <string>
#include <iostream>
// 定义一个可以存储int, double, std::string的variant
using MyVariant = std::variant<int, double, std::string>;
// 定义一个访问器,可以是函数对象
struct MyVisitor {
void operator()(int i) const {
std::cout << "当前存储的是整数: " << i << std::endl;
}
void operator()(double d) const {
std::cout << "当前存储的是浮点数: " << d << std::endl;
}
void operator()(const std::string& s) const {
std::cout << "当前存储的是字符串: " << s << std::endl;
}
};
int main() {
MyVariant var; // 默认构造为第一个类型,即int,值为0
var = 123;
std::visit(MyVisitor{}, var); // 输出:当前存储的是整数: 123
var = 4.56;
std::visit(MyVisitor{}, var); // 输出:当前存储的是浮点数: 4.56
var = "Hello, C++17!";
std::visit(MyVisitor{}, var); // 输出:当前存储的是字符串: Hello, C++17!
// 尝试错误地使用std::get
try {
std::cout << "尝试获取int: " << std::get<int>(var) << std::endl;
} catch (const std::bad_variant_access& e) {
std::cerr << "错误: " << e.what() << std::endl; // 输出错误信息
}
// 安全地使用std::get_if
if (const std::string* s_ptr = std::get_if<std::string>(&var)) {
std::cout << "安全获取字符串: " << *s_ptr << std::endl;
}
return 0;
}这段代码展示了
std::variant
std::visit
std::get
std::get_if
std::variant
union
这问题问得好,也是很多从C++11/14时代过来的开发者心中的疑问。毕竟以前我们不是没法实现多类型存储,
union
union
int
double
union
std::string
用基类指针实现多态固然强大,但它也有自己的适用场景和开销。首先,你得先设计一个基类,然后所有可能的类型都得继承它。这会引入虚函数表(vtable)的运行时开销,而且通常涉及到堆内存分配,你需要自己管理内存(
std::unique_ptr
std::shared_ptr
dynamic_cast
nullptr
相比之下,
std::variant
std::visit
std::variant
任何一个强大的工具,用起来都会有些门道,
std::variant
一个常见的问题是,如果你
std::variant
std::variant<MyClass, int> v;
std::monostate
以上就是C++如何使用std::variant实现多类型安全存储的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号