亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++聯合體union用法實例詳解

2020-05-23 14:19:48
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了C++聯合體union用法,較為詳細的分析了C++中聯合體的概念、實用技巧及相關注意事項,需要的朋友可以參考下

本文實例講述了C++聯合體union用法。分享給大家供大家參考。具體如下:

我們應該按照C中的convention去使用union,這是我這篇文章要給出的觀點。雖然C++使得我們可以擴展一些新的東西進去,但是,我建議你不要那樣去做,看完這篇文章之后,我想你大概也是這么想的。

C由于沒有類的概念,所有類型其實都可以看作是基本類型的組合,因此在union中包含struct也就是一件很自然的事情了,到了C++之后,既然普遍認為C++中的struct與class基本等價,那么union中是否可以有類成員呢?先來看看如下的代碼:

 

 
  1. struct TestUnion 
  2.    TestUnion() {} 
  3. }; 
  4.  
  5. typedef union 
  6.    TestUnion obj; 
  7. } UT; 
  8.  
  9. int main (void
  10.    return 0; 

編譯該程序,我們將被告知:

error C2620: union '__unnamed' : member 'obj' has user-defined constructor or non-trivial default constructor

而如果去掉那個什么也沒干的構造函數,則一切OK。

為什么編譯器不允許我們的union成員有構造函數呢?我無法找到關于這個問題的比較權威的解釋,對這個問題,我的解釋是:

如果C++標準允許我們的union有構造函數,那么,在進行空間分配的時候要不要執行這個構造函數呢?如果答案是yes,那么如果TestUnion 的構造函數中包含了一些內存分配操作,或者其它對整個application狀態的修改,那么,如果我今后要用到obj的話,事情可能還比較合理,但是如果我根本就不使用obj這個成員呢?由于obj的引入造成的對系統狀態的修改顯然是不合理的;反之,如果答案是no,那么一旦我們今后選中了obj來進行 操作,則所有信息都沒有初始化(如果是普通的struct,沒什么問題,但是,如果有虛函數呢?)。更進一步,假設現在我們的union不是只有一個 TestUnion obj,還有一個TestUnion2 obj2,二者均有構造函數,并且都在構造函數中執行了一些內存分配的工作(甚至干了很多其它事情),那么,如果先構造obj,后構造obj2,則執行的 結果幾乎可以肯定會造成內存的泄漏。

鑒于以上諸多麻煩(可能還有更多麻煩),在構造union時,編譯器只負責分配空間,而不負責去執行附加的初始化工作,為了簡化工作,只要我們提供了構造函數,就會收到上面的error。

同理,除了不能加構造函數,析構函數/拷貝構造函數/賦值運算符也是不可以加。

此外,如果我們的類中包含了任何virtual函數,編譯時,我們將收到如下的錯誤信息:

error C2621: union '__unnamed' : member 'obj' has copy constructor

所以,打消在union中包含有構造函數/析構函數/拷貝構造函數/賦值運算符/虛函數的類成員變量的念頭,老老實實用你的C風格struct吧!

不過,定義普通的成員函數是OK的,因為這不會使得class與C風格的struct有任何本質區別,你完全可以將這樣的class理解為一個C風格的struct + n個全局函數。

現在,再看看在類中包含內部union時會有什么不同??纯聪旅娴某绦?,并請注意閱讀程序提示:

 

 
  1. class TestUnion 
  2.    union DataUnion 
  3.    { 
  4.    DataUnion(const char*); 
  5.    DataUnion(long); 
  6.    const char* ch_; 
  7.    long l_; 
  8.    } data_; 
  9.  
  10.   public
  11.    TestUnion(const char* ch); 
  12.    TestUnion(long l); 
  13. }; 
  14.  
  15. TestUnion::TestUnion(const char* ch) : data_(ch) // if you want to use initialzing list to initiate a nested-union member, the union must not be anonymous and must have a constructor。 
  16. {} 
  17.  
  18. TestUnion::TestUnion(long l) : data_(l) 
  19. {} 
  20.  
  21. TestUnion::DataUnion::DataUnion(const char* ch) : ch_(ch) 
  22. {} 
  23.  
  24. TestUnion::DataUnion::DataUnion(long l) : l_(l) 
  25. {} 
  26.  
  27. int main (void
  28.    return 0; 

正如上面程序所示,C++中的union也可以包含構造函數,但是,這雖然被語言所支持,但實在是一種不佳的編程習慣,因此, 我不打算對上面的程序進行過多的說明。我更推薦如下的編程風格:

 

 
  1. class TestUnion 
  2.    union DataUnion 
  3.    { 
  4.    const char* ch_; 
  5.    long l_; 
  6.    } data_; 
  7.    
  8.   public
  9.    TestUnion(const char* ch); 
  10.    TestUnion(long l); 
  11. }; 
  12.  
  13. TestUnion::TestUnion(const char* ch) 
  14.    data_.ch_ = ch; 
  15.  
  16. TestUnion::TestUnion(long l) 
  17.    data_.l_ = l; 
  18.  
  19. int main (void
  20.    return 0; 

它完全是C風格的。

所以,接受這個結論吧:

請按照C中的convention去使用union,盡量不要嘗試使用任何C++附加特性。

union是個好東西,union是個struct,里面所有成員共享一塊內存,大小由size最大的member決定,存取成員的時候會以成員的類型來解析這塊內存;在gamedev中,union可以在這些方面有所作為:

1. 換名:

 

 
  1. struct Rename 
  2. public
  3. union 
  4. struct 
  5. float x,y,z,w; 
  6. }; 
  7. struct 
  8. float vec[4]; 
  9. }; 
  10. }; 
  11. }; 

這樣我們既可以根據具體的含義來訪問變量,也可以象數組一樣的loop;

2 .壓縮:

 

 
  1. struct Compression 
  2. public
  3. bool operator==(const Compression& arg) const { return value == arg.value; } 
  4. union 
  5. struct 
  6. char a,b,c,d,e,f,g; 
  7. }; 
  8. struct 
  9. long long value; 
  10. }; 
  11. }; 
  12. }; 

這樣對于集中處理的情況,比如==,就會大幅度提高效率,象在64位機上,只要一次,或者傳輸數據的情況,壓縮解壓縮都非常方便;

3. 危險:

匿名的union用法,不是standard,所以在compiler上要確認==>編譯器移植性不好;

不同的機器操作系統上數據的size都是不一樣,表示不一樣,那么在用union的時候,尤其是在移植的時候,都是危險的情況;

但是如果系統,compiler都是一樣的話,在合適的地方使用union還是可以的。

聯合(union)在C/C++里面見得并不多,但是在一些對內存要求特別嚴格的地方,聯合又是頻繁出現,那么究竟什么是聯合、怎么去用、有什么需要注意的地方呢?就這些問題,我試著做一些簡單的回答,里面肯定還有不當的地方,歡迎指出!

1、什么是聯合?

“聯合”是一種特殊的類,也是一種構造類型的數據結構。在一個“聯合”內可以定義多種不同的數據類型, 一個被說明為該“聯合”類型的變量中,允許裝入該“聯合”所定義的任何一種數據,這些數據共享同一段內存,已達到節省空間的目的(還有一個節省空間的類型:位域)。 這是一個非常特殊的地方,也是聯合的特征。另外,同struct一樣,聯合默認訪問權限也是公有的,并且,也具有成員函數。

2、聯合與結構的區別?

“聯合”與“結構”有一些相似之處。但兩者有本質上的不同。在結構中各成員有各自的內存空間, 一個結構變量的總長度是各成員長度之和(空結構除外,同時不考慮邊界調整)。而在“聯合”中,各成員共享一段內存空間, 一個聯合變量的長度等于各成員中最長的長度。應該說明的是, 這里所謂的共享不是指把多個成員同時裝入一個聯合變量內, 而是指該聯合變量可被賦予任一成員值,但每次只能賦一種值, 賦入新值則沖去舊值。

下面舉一個例了來加對深聯合的理解。

例4:

 

 
  1. #include <stdio.h> 
  2. void main() 
  3. union number 
  4. /*定義一個聯合*/ 
  5. int i; 
  6. struct 
  7. /*在聯合中定義一個結構*/ 
  8. char first; 
  9. char second; 
  10. }half; 
  11. }num; 
  12. num.i=0x4241; /*聯合成員賦值*/ 
  13. printf("%c%c/n", num.half.first, num.half.second); 
  14. num.half.first='a'/*聯合中結構成員賦值*/ 
  15. num.half.second='b'
  16. printf("%x/n", num.i); 
  17. getchar(); 

輸出結果為:

AB

6261

從上例結果可以看出: 當給i賦值后, 其低八位也就是first和second的值; 當給first和second賦字符后, 這兩個字符的ASCII碼也將作為i 的低八位和高八位。

3、如何定義?

例如:

 

 
  1. union test 
  2. test() { } 
  3. int office; 
  4. char teacher[5]; 
  5. }; 

定義了一個名為test的聯合類型,它含有兩個成員,一個為整型,成員名office;另一個為字符數組,數組名為teacher。聯合定義之后,即可進行聯合變量說明,被說明為test類型的變量,可以存放整型量office或存放字符數組teacher。

4、如何說明?

聯合變量的說明有三種形式:先定義再說明、定義同時說明和直接說明。

以test類型為例,說明如下:

1)

 

 
  1. union test 
  2. int office; 
  3. char teacher[5]; 
  4. };  
  5. union test a,b; /*說明a,b為test類型*/ 

2)

 

 
  1. union test 
  2. int office; 
  3. char teacher[5]; 
  4. } a,b; 

3)

 

 
  1. union 
  2. int office; 
  3. char teacher[5]; 
  4. } a,b; 

經說明后的a,b變量均為test類型。a,b變量的長度應等于test的成員中最長的長度,即等于teacher數組的長度,共5個字節。a,b變量如賦予整型值時,只使用了4個字節,而賦予字符數組時,可用5個字節。

5、如何使用?

對聯合變量的賦值,使用都只能是對變量的成員進行。聯合變量的成員表示為:

聯合變量名.成員名

例如,a被說明為test類型的變量之后,可使用a.class、a.office

不允許只用聯合變量名作賦值或其它操作,也不允許對聯合變量作初始化賦值,賦值只能在程序中進行。

還要再強調說明的是,一個聯合變量,每次只能賦予一個成員值。換句話說,一個聯合變量的值就是聯合變員的某一個成員值。

6、匿名聯合

匿名聯合僅僅通知編譯器它的成員變量共同享一個地址,而變量本身是直接引用的,不使用通常的點號運算符語法.

例如:

 

 
  1. #include <iostream> 
  2. void main() 
  3. union{  
  4. int test; 
  5. char c;  
  6. };  
  7. test=5; 
  8. c='a'
  9. std::cout<<i<<" "<<c; 

正如所見到的,聯合成分象聲明的普通局部變量那樣被引用,事實上對于程序而言,這也正是使用這些變量的方式.另外,盡管被定義在一個聯合聲明中,他們與同一個程序快那的任何其他局部變量具有相同的作用域級別.這意味這匿名聯合內的成員的名稱不能與同一個作用域內的其他一直標志符沖突.

對匿名聯合還存在如下限制:

因為匿名聯合不使用點運算符,所以包含在匿名聯合內的元素必須是數據,不允許有成員函數,也不能包含私有或受保護的成員。還有,全局匿名聯合必須是靜態(static)的,否則就必須放在匿名名字空間中。

7、幾點需要討論的地方:

1)聯合里面那些東西不能存放?

我們知道,聯合里面的東西共享內存,所以靜態、引用都不能用,因為他們不可能共享內存。

2)類可以放入聯合嗎?

我們先看一個例子:

 

 
  1. class Test 
  2. public
  3. Test():data(0) { } 
  4. private
  5. int data; 
  6. }; 
  7. typedef union _test 
  8. Test test;  
  9. }UI;  

編譯通不過,為什么呢?

因為聯合里不允許存放帶有構造函數、析夠函數、復制拷貝操作符等的類,因為他們共享內存,編譯器無法保證這些對象不被破壞,也無法保證離開時調用析夠函數。

3)又是匿名惹的禍??

我們先看下一段代碼:

 

 
  1. class test 
  2. public
  3. test(const char* p); 
  4. test(int in); 
  5. const operator char*() const {return 
  6. data.ch;} 
  7. operator long() const {return data.l;} 
  8. private
  9. enum type {Int, String }; 
  10. union 
  11. const char* ch; 
  12. int i; 
  13. }datatype; 
  14. type stype; 
  15. test(test&); 
  16. test& operator=(const test&); 
  17. }; 
  18. test::test(const char *p):stype 
  19. (String),datatype.ch(p) { } 
  20. test::test(int in):stype(Int),datatype.l(i) { 

看出什么問題了嗎?呵呵,編譯通不過。為什么呢?難道datatype.ch(p)和datatype.l(i)有問題嗎?

哈哈,問題在哪呢?讓我們來看看構造test對象時發生了什么,當創建test對象時,自然要調用其相應的構造函數,在構造函數中當然要調用其成員的構造函數,所以其要去調用datatype成員的構造函數,但是他沒有構造函數可調用,所以出

錯。

注意了,這里可并不是匿名聯合!因為它后面緊跟了個data!

4)如何有效的防止訪問出錯?

使用聯合可以節省內存空間,但是也有一定的風險:通過一個不適當的數據成員獲取當前對象的值!例如上面的ch、i交錯訪問。

為了防止這樣的錯誤,我們必須定義一個額外的對象,來跟蹤當前被存儲在聯合中的值得類型,我們稱這個額外的對象為:union的判別式。

一個比較好的經驗是,在處理作為類成員的union對象時,為所有union數據類型提供一組訪問函數。

希望本文所述對大家的C++程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
午夜精品一区二区三区视频免费看| 欧美超级免费视 在线| 91在线观看免费高清| 久久精品夜夜夜夜夜久久| 欧美性受xxxx黑人猛交| 欧美专区福利在线| 日韩中文有码在线视频| 亚洲男人天堂网站| 91精品国产电影| 亚洲精品视频播放| 在线观看日韩视频| 2019中文字幕在线| 91成人精品网站| 亚洲色图偷窥自拍| 欧美一级黑人aaaaaaa做受| 2025国产精品视频| 亚洲欧美国产精品久久久久久久| 成人久久18免费网站图片| 日韩欧美极品在线观看| 亚洲欧美日韩精品久久亚洲区| 欧美夜福利tv在线| 国产又爽又黄的激情精品视频| 日本高清不卡在线| 91精品国产综合久久香蕉922| 亚洲精品一区二区三区不| 午夜精品视频网站| 伊人亚洲福利一区二区三区| 久久久久久免费精品| 粗暴蹂躏中文一区二区三区| 国产不卡av在线免费观看| 亚洲片在线观看| 欧美精品videosex极品1| 欧洲永久精品大片ww免费漫画| 欧美在线观看一区二区三区| 欧美三级欧美成人高清www| 亚洲欧美激情视频| yellow中文字幕久久| 亚洲高清免费观看高清完整版| 亚洲aaa激情| 国产91成人在在线播放| 日韩av电影国产| 欧美精品精品精品精品免费| 日韩电影网在线| 欧美极品在线视频| 中文字幕日韩有码| 97超级碰在线看视频免费在线看| 国产精品免费视频xxxx| 日韩av片免费在线观看| 欧美电影在线观看完整版| 一本色道久久88综合亚洲精品ⅰ| 日韩av综合网| 成人国产精品一区| 色吧影院999| 欧美成人黑人xx视频免费观看| 伊人一区二区三区久久精品| 精品视频—区二区三区免费| 久久久综合免费视频| 亚洲一区二区久久久| 国产精品激情av电影在线观看| 欧美电影院免费观看| 精品国产福利在线| 亚洲男女自偷自拍图片另类| 国产乱人伦真实精品视频| 亚洲国产成人精品久久| 一本一道久久a久久精品逆3p| 久久免费少妇高潮久久精品99| 5566日本婷婷色中文字幕97| 色综合久久精品亚洲国产| 精品偷拍一区二区三区在线看| 亚洲人成电影在线播放| 亚州av一区二区| 亚洲精品中文字幕有码专区| 68精品国产免费久久久久久婷婷| 热久久免费国产视频| 97**国产露脸精品国产| 国产成人在线视频| 中文字幕精品—区二区| 久久这里只有精品99| 亚洲aⅴ日韩av电影在线观看| 亲子乱一区二区三区电影| 日韩av在线导航| 国产精品尤物福利片在线观看| www.亚洲一二| 国产99久久精品一区二区| 日韩亚洲一区二区| 视频直播国产精品| 亚洲国内精品视频| 亚洲女人被黑人巨大进入| 国产精品综合网站| 亚洲美女av黄| 中文字幕一区二区精品| 欧美性猛交xxxx久久久| 超碰日本道色综合久久综合| 午夜欧美大片免费观看| 国产激情综合五月久久| 欧美视频一区二区三区…| 国产精品高潮呻吟久久av黑人| 亚洲欧美日韩精品| 欧美刺激性大交免费视频| 亚洲精品小视频| 亚洲午夜精品久久久久久性色| 亚洲影院高清在线| www.99久久热国产日韩欧美.com| 欧美理论电影网| 狠狠操狠狠色综合网| 91社区国产高清| 精品久久久久国产| 欧美精品久久久久久久久| 成人国产精品一区二区| 日韩美女主播视频| 亚洲新中文字幕| 欧美大尺度在线观看| 在线观看日韩视频| 亚洲免费成人av电影| 久久久久久久久网站| 国产成人精品综合久久久| 欧美激情视频在线免费观看 欧美视频免费一| 国产亚洲精品久久| 91极品女神在线| 欧美日韩激情视频8区| 久久久久99精品久久久久| 久久视频免费观看| 欧美日韩aaaa| www.精品av.com| 国产欧美一区二区三区在线看| 亚洲丁香久久久| 91性高湖久久久久久久久_久久99| 日韩有码在线视频| 亚洲自拍小视频免费观看| 欧美性黄网官网| 免费99精品国产自在在线| 国产有码一区二区| 亚洲天堂第二页| 最好看的2019年中文视频| 日本三级久久久| 亚洲欧美一区二区三区四区| 精品露脸国产偷人在视频| 国产主播欧美精品| 国产91精品青草社区| 色婷婷av一区二区三区在线观看| 中文字幕国产日韩| 久久人人爽人人爽人人片亚洲| 欧美性猛交xxxxx免费看| 欧美大片在线免费观看| 成人在线中文字幕| 亚洲性69xxxbbb| 国产精品99久久久久久久久久久久| 亚洲精品乱码久久久久久金桔影视| 在线观看亚洲区| 亚洲男人的天堂在线| 欧美一级高清免费| 国产精品久久久久久久电影| 久久91精品国产91久久跳| 日韩精品中文字幕久久臀| 亚洲电影av在线| 岛国av午夜精品| 精品日韩视频在线观看| 成人在线中文字幕| 成人字幕网zmw| 亚洲一区二区三区777| 欧美电影免费观看高清| 国产精品video| 精品国产91久久久久久老师| 久久精品久久久久久|