variant模板

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{	//8byte
    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{//2*8=16
    double x{};
    double y{};
};
struct WidgetC{//6*8=48
    double x{};
    double y{};
    double z{};
    double u{};
    double v{};
    double w{};
};

union WidgetABCU{
    WidgetA a;
    WidgetB b;
    WidgetC c;

    WidgetABCU(){}
    ~WidgetABCU(){}
};

struct MyVisitor {	//重载3个调用操作符

  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{};//move
        WidgetABC w2=w1;	//copy
        cout<<sizeof(w1)<<endl; //内存模型,最大容量48,加上类型说明,8byte

        MyVisitor visitor;

        std::visit(visitor, w1);
    }
    cout<<"union : -----------"<<endl;
    {
        WidgetABCU w3;	//结束后,没有析构,使用的C的值语义
        cout<<sizeof(w3)<<endl;
        w3.a= WidgetA();	//此时对w3做初始化

        cout<<sizeof(w3)<<endl;

        //w3.a.~WidgetA();	//此处需要手动析构,不安全
    }

    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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术的微光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值