Effective C++:unio
生活随笔
收集整理的這篇文章主要介紹了
Effective C++:unio
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
聯合是一種特殊的類。一個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 <iostream> #include <vector> #include <cstdint>//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<char>(0x62)<< std::endl;return 0; }?
針對內置類型:
#include <iostream> #include <memory> #include <string>template<typename T> class Node { private:T data;public:Node(const T& data_) :data(data_) {}~Node() = default;Node(const Node<T>& other) :data(other.data) {}Node<T>& operator=(const Node<T>& other) { this->data = other.data; return *this; };Node<T>& operator=(Node<T>&& other) { this->data = std::move(other.data); return *this; }Node(Node<T>&& other) :data(std::move(other.data)) {}template<typename Ty>friend std::ostream& operator<<(std::ostream& os, const Node<Ty>& node); };template<typename Ty> std::ostream& operator<<(std::ostream& os, const Node<Ty>& 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<std::string> strNode; //error.Node<int> node; //ok,模板類類型.Tree tree;char c;~InnerClass() { std::cout << "----------------" << std::endl; } //注意這里,我們顯式的寫出了析構函數. };//case 4: template<typename T> union InnerTem {Node<T> node;Tree tree; };int main() {//case 1:Token tk = { 't' };//case 2:iVal = 20;//case 3:InnerClass inCls = { "shihua" };//case 4:InnerTem<int> inTem = { 50 };//case 4.5://InnerTem<std::string> 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 <iostream> #include <string>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
總結
以上是生活随笔為你收集整理的Effective C++:unio的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IOS笔记 本地化多语言支持
- 下一篇: 当猪飞起来:也谈创业初期商业模式问题