博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective C++:unio
阅读量:6441 次
发布时间:2019-06-23

本文共 6167 字,大约阅读时间需要 20 分钟。

hot3.png

联合是一种特殊的类。一个union可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当我们给union中的某个成员赋值的之后,该union中的其他成员变成了未定义的状态。

需要特别注意的是:

1,当给一个union类型分配空间的时候至少要分配能容纳它的最大的数据成员的空间。

2,C++11新标准中规定除了内置类型(int, double...),带有构造函数和析构函数的类型也可以作为union的成员类型。

3,union也可以为其成员指定public, private, ptorected等权限标记符。但是默认情况下都是public的。

4,union不可以继承自其他class,也不能被其他class继承.

5,union类型编译器是不会自动合成析构函数的我们可以通过显式的写出来来保证非POD和内置类型的析构函数被调用.

 

使用union在编译时间做big-endian和little-endian的判断:

#include 
#include
#include
//static union { std::int32_t mylong; char c[4]; } endian_test = { 0x623f3f6c };union endian_test { std::int32_t mylong; char c[4]; };static constexpr endian_test test{ 0x623f3f6c };inline static constexpr bool is_little_end(void) { return /*endian_*/test.c[0] == 'l'; }inline static constexpr bool is_big_end(void) { return /*endian_*/test.c[0] == 'b'; }int main(){ std::cout << std::boolalpha << is_little_end() << std::endl; std::cout << static_cast
(0x62)<< std::endl; return 0;}

 

针对内置类型:

#include 
#include
#include
template
class Node {private: T data;public: Node(const T& data_) :data(data_) {} ~Node() = default; Node(const Node
& other) :data(other.data) {} Node
& operator=(const Node
& other) { this->data = other.data; return *this; }; Node
& operator=(Node
&& other) { this->data = std::move(other.data); return *this; } Node(Node
&& other) :data(std::move(other.data)) {} template
friend std::ostream& operator<<(std::ostream& os, const Node
& node);};template
std::ostream& operator<<(std::ostream& os, const Node
& node){ os << node.data; return os;}class Tree {private: int number;public: Tree(const int& num) :number(num) {} Tree(const Tree& other) :number(other.number) {} Tree(Tree&& other) :number(std::move(other.number)) {} Tree& operator=(const Tree& other) { this->number = other.number; return *this; } Tree& operator=(Tree&& other) { this->number = std::move(other.number); return *this; } ~Tree() = default; friend std::ostream& operator<<(std::ostream& os, const Tree& other);};std::ostream& operator<<(std::ostream& os, const Tree& other){ os << other.number; return os;}//case 1:union Token { int ival; double dval; char cval;};//case 2:static union { char carVal; int iVal;};//case 3:union InnerClass { Node
strNode; //error. Node
node; //ok,模板类类型. Tree tree; char c; ~InnerClass() { std::cout << "----------------" << std::endl; } //注意这里,我们显式的写出了析构函数.};//case 4:template
union InnerTem { Node
node; Tree tree;};int main(){ //case 1: Token tk = { 't' }; //case 2: iVal = 20; //case 3: InnerClass inCls = { "shihua" }; //case 4: InnerTem
inTem = { 50 }; //case 4.5: //InnerTem
inStr = { "shihua" }; //error错误.因为union没有析构函数. std::cout << tk.cval << std::endl; std::cout << iVal << std::endl; std::cout << inCls.strNode << std::endl; std::cout << inTem.node << std::endl; return 0;}

针对类类型:

#include 
#include
class ManageTk{ private: //匿名联合类型. union{ int iVal; //int类型. char cVal; //char类型. std::string sVal; //类类型std::string }; enum : int { CHAR, INT, STR } type; //type为匿名enum类型. void copyUnion(const ManageTk& other); public: ManageTk():iVal(0), type(INT){} ManageTk(const int& val):iVal(val), type(INT){} ManageTk(const ManageTk& other); ManageTk(ManageTk&& other); ManageTk& operator=(const ManageTk& other); ManageTk& operator=(ManageTk&& other); ManageTk& operator=(const int& val); ManageTk& operator=(const char& val); ManageTk& operator=(const std::string& val); ~ManageTk(); };ManageTk::ManageTk(const ManageTk& other){ if(this->type == STR && other.type != STR){ //如果当前union包含的是std::string,而other所包含的是其他类型 using namespace std; sVal.~string(); //那么先释放掉当前std::string的内存. } if(this->type == STR && other.type == STR){ //如果当前union包含的是std::string,而other包含的是也是std::string (this->sVal) = other.sVal; //那么直接用other所包含的std::string赋值当前std::string. }else{ this->copyUnion(other); //如果是其他的情况. } this->type = other.type;}void ManageTk::copyUnion(const ManageTk& other){ switch(other.type){ case INT: { (this->iVal) = other.iVal; //如果other说包含的是int类型. break; } case CHAR: { (this->cVal) = other.cVal; //如果other所包含的是char类型. break; } case STR: { new(&(this->sVal)) std::string(other.sVal); //如果other包含的是std::string类型,当前union包含的是其他类型. break; //这个时候当前union所包含的std::string还处于未定义状态. } //最好还是用new的定位形式赋值. }}ManageTk::ManageTk(ManageTk&& other){ if(this->type == STR && other.type != STR){ using namespace std; (this->sVal).~string(); } if(this->type == STR && other.type == STR){ (this->sVal) = other.sVal; }else{ this->copyUnion(other); } this->type = other.type;}ManageTk& ManageTk::operator=(const ManageTk& other){ if(this->type == STR && other.type != STR){ using namespace std; (this->sVal).~string(); } if(this->type == STR && other.type == STR){ (this->sVal) = other.sVal; }else{ this->copyUnion(other); } this->type = other.type; return *this;}ManageTk& ManageTk::operator=(ManageTk&& other){ if(this->type == STR && other.type != STR){ using namespace std; (this->sVal).~string(); } if(this->type == STR && other.type == STR){ (this->sVal) = other.sVal; }else{ this->copyUnion(other); } this->type = other.type; return *this;}ManageTk& ManageTk::operator=(const int& val){ if(this->type == STR){ using namespace std; (this->sVal).~string(); } this->iVal = val; this->type = INT; return *this;}ManageTk& ManageTk::operator=(const char& val){ if(this->type == STR){ using namespace std; (this->sVal).~string(); } this->iVal = val; this->type = CHAR; return *this;}ManageTk& ManageTk::operator=(const std::string& val){ if(this->type == STR){ this->sVal = val; }else{ new(&(this->sVal)) std::string(val); } this->type = STR; return *this;}ManageTk::~ManageTk(){ if(this->type == STR){ using namespace std; (this->sVal).~string(); }}int main(){ ManageTk un; return 0;}

 

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/708956

你可能感兴趣的文章
MaxCompute与OSS非结构化数据读写互通(及图像处理实例)
查看>>
【F3简介】一张图看懂FPGA-F3实例
查看>>
bash环境(变量与bash配置文件)
查看>>
Server Hard drive mode
查看>>
smb服务器配置过程遇到错误及解决
查看>>
java杂乱
查看>>
在Linux上安装Python3.6.1
查看>>
[基础]iOS 可视化编程(全系列)
查看>>
我的友情链接
查看>>
LVS之NAT模型配置实验
查看>>
nginx 报错 99: Cannot assign requested address
查看>>
几种流行的AJAX框架:jQuery,Mootools,Dojo,Ext JS的对比
查看>>
Socket-Client通信
查看>>
Maven搭建简单的SS项目
查看>>
#我要上首页# 新版博客首页来了,做明星博主还会远吗?
查看>>
PHP缓存技术
查看>>
关于SOCKET资源堆栈
查看>>
笔记 百度搜索
查看>>
控制台 - 网络管理之华为交换机 S系列端口限速
查看>>
我的友情链接
查看>>