std::variant<> 模板
C++使用variant取代C中的union,本质还是struct的一个特化板
定义一个结构中有多个变量,内存存储多个强类型中的一个,且保存有当前保存的类型索引
union和variant
union类型不安全,不支持对象语义和RAII,需要手动维护
variant类型安全,自动支持对象语义和RAII
应用推荐:
基本类型使用union
自定义类型使用std::variant
可以使用std::visit搭配访问visitor,支持对类型的多态访问
variant的内存模型:最大的类型+8byte的索引,无需额外堆内存分配
典型场合:
1:返回值或参数,多选一
2:特殊错误处理variant<ReturnObject, ErrorCode>
3: 不适合虚函数的多态visitor
示例代码
#include <iostream>
#include <any>
#include <variant>
using namespace std;
int alloc_times = 0;
int dealloc_times = 0;
int allocated = 0;
void* operator new(size_t size) {
void* p = std::malloc(size);
allocated+=size;
alloc_times++;
return p;
}
void operator delete(void* p) noexcept {
dealloc_times++;
return std::free(p);
}
void* operator new[](size_t size) {
void* p = std::malloc(size);
allocated+=size;
alloc_times++;
return p;
}
void operator delete[](void* p) noexcept {
dealloc_times++;
return std::free(p);
}
struct WidgetA{
double x{};
WidgetA(){
cout<<"default ctor"<<endl;
}
WidgetA(const WidgetA& w)
{
cout<<"copy ctor"<<endl;
}
WidgetA& operator=(const WidgetA& w)
{
cout<<"assignment ="<<endl;
return *this;
}
WidgetA(WidgetA&& w)
{
cout<<"move ctor"<<endl;
}
~WidgetA(){
cout<<"dtor"<<endl;
}
};
struct WidgetB{
double x{};
double y{};
};
struct WidgetC{
double x{};
double y{};
double z{};
double u{};
double v{};
double w{};
};
union WidgetABCU{
WidgetA a;
WidgetB b;
WidgetC c;
WidgetABCU(){}
~WidgetABCU(){}
};
struct MyVisitor {
void operator()(WidgetA const& a) {
cout << "It's an WidgetA!"<<endl;
}
void operator()(WidgetB const& b) {
cout << "It's a WidgetB!"<<endl;
}
void operator()(WidgetC const& b) {
cout << "It's a WidgetC!"<<endl;
}
};
int main(){
using WidgetABC = std::variant<WidgetA, WidgetB,WidgetC>;
cout<<"std::variant : -----------"<<endl;
{
WidgetABC w1=WidgetA{};
WidgetABC w2=w1;
cout<<sizeof(w1)<<endl;
MyVisitor visitor;
std::visit(visitor, w1);
}
cout<<"union : -----------"<<endl;
{
WidgetABCU w3;
cout<<sizeof(w3)<<endl;
w3.a= WidgetA();
cout<<sizeof(w3)<<endl;
}
cout<<"总分配:"<< allocated<<" bytes, 分配次数:"<<alloc_times<<" 释放次数:"<<dealloc_times<<endl;
}
测试结果
kongcb@tcu-pc:~/testcode/template/type$ ./variant1
std::variant : -----------
default ctor
move ctor
dtor
copy ctor
56
It's an WidgetA!
dtor
dtor
union : -----------
48
default ctor
assignment =
dtor
48
总分配:0 bytes, 分配次数:0 释放次数:0