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

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

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

2020-01-26 15:06:10
字體:
來源:轉載
供稿:網友

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

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

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

struct TestUnion{    TestUnion() {}};typedef union{    TestUnion obj;} UT;int main (void){    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時會有什么不同??纯聪旅娴某绦颍⒄堊⒁忾喿x程序提示:

class TestUnion{    union DataUnion    {      DataUnion(const char*);      DataUnion(long);      const char* ch_;      long l_;    } data_;  public:    TestUnion(const char* ch);    TestUnion(long l);};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。{}TestUnion::TestUnion(long l) : data_(l){}TestUnion::DataUnion::DataUnion(const char* ch) : ch_(ch){}TestUnion::DataUnion::DataUnion(long l) : l_(l){}int main (void){    return 0;}

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

class TestUnion{    union DataUnion    {      const char* ch_;      long l_;    } data_;    public:    TestUnion(const char* ch);    TestUnion(long l);};TestUnion::TestUnion(const char* ch){    data_.ch_ = ch;}TestUnion::TestUnion(long l){    data_.l_ = l;}int main (void){    return 0;}

它完全是C風格的。

所以,接受這個結論吧:

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

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

1. 換名:

struct Rename{  public:    union    {      struct       {        float x,y,z,w;      };      struct      {        float vec[4];      };    };};

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

 2 .壓縮:

struct Compression{ public:   bool operator==(const Compression& arg) const { return value == arg.value; }   union   {     struct      {       char a,b,c,d,e,f,g;     };     struct     {       long long value;     };   };};

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

3. 危險:

匿名的union用法,不是standard,所以在compiler上要確認==>編譯器移植性不好;
不同的機器操作系統上數據的size都是不一樣,表示不一樣,那么在用union的時候,尤其是在移植的時候,都是危險的情況;
但是如果系統,compiler都是一樣的話,在合適的地方使用union還是可以的。

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

1、什么是聯合?

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

2、聯合與結構的區別?

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

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

例4:

#include <stdio.h>void main(){  union number  { /*定義一個聯合*/   int i;   struct   { /*在聯合中定義一個結構*/    char first;    char second;   }half;  }num;  num.i=0x4241; /*聯合成員賦值*/  printf("%c%c/n", num.half.first, num.half.second);  num.half.first='a'; /*聯合中結構成員賦值*/  num.half.second='b';  printf("%x/n", num.i);  getchar();}

輸出結果為:

AB
6261

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

3、如何定義?

例如:

union test{  test() { }  int office;  char teacher[5];};

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

4、如何說明?

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

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

union test{  int office;  char teacher[5];}; union test a,b; /*說明a,b為test類型*/

2)

union test{  int office;  char teacher[5];} a,b;

3)

union {  int office;  char teacher[5];} a,b;

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

5、如何使用?

對聯合變量的賦值,使用都只能是對變量的成員進行。聯合變量的成員表示為:
聯合變量名.成員名
例如,a被說明為test類型的變量之后,可使用a.class、a.office
不允許只用聯合變量名作賦值或其它操作,也不允許對聯合變量作初始化賦值,賦值只能在程序中進行。
還要再強調說明的是,一個聯合變量,每次只能賦予一個成員值。換句話說,一個聯合變量的值就是聯合變員的某一個成員值。

6、匿名聯合

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

#include <iostream>void main(){  union{   int test;  char c;   };   test=5;  c='a';  std::cout<<i<<" "<<c;}

正如所見到的,聯合成分象聲明的普通局部變量那樣被引用,事實上對于程序而言,這也正是使用這些變量的方式.另外,盡管被定義在一個聯合聲明中,他們與同一個程序快那的任何其他局部變量具有相同的作用域級別.這意味這匿名聯合內的成員的名稱不能與同一個作用域內的其他一直標志符沖突.
對匿名聯合還存在如下限制:
因為匿名聯合不使用點運算符,所以包含在匿名聯合內的元素必須是數據,不允許有成員函數,也不能包含私有或受保護的成員。還有,全局匿名聯合必須是靜態(static)的,否則就必須放在匿名名字空間中。

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

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

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

2)類可以放入聯合嗎?

我們先看一個例子:

class Test{  public:  Test():data(0) { }  private:  int data;};typedef union _test{  Test test; }UI; 

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

3)又是匿名惹的禍??
我們先看下一段代碼:

class test{  public:  test(const char* p);  test(int in);  const operator char*() const {return  data.ch;}  operator long() const {return data.l;}  private:  enum type {Int, String };  union   {   const char* ch;   int i;  }datatype;  type stype;  test(test&);  test& operator=(const test&);};test::test(const char *p):stype(String),datatype.ch(p) { }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
精品久久久久久久久久久久| 国内偷自视频区视频综合| 国产精品旅馆在线| 亚洲色图日韩av| 日韩精品视频中文在线观看| 欧美日本亚洲视频| 国产欧美在线看| 欧美激情精品久久久| 日韩免费av在线| 国产精品丝袜久久久久久不卡| 亚洲色图15p| 精品久久久久久久久久ntr影视| 亚洲影院色无极综合| 亚洲已满18点击进入在线看片| 日韩免费观看av| 亚洲片在线观看| 国产激情久久久久| 久久久国产成人精品| 欧美肥老太性生活视频| 久久视频在线直播| 2019中文字幕在线观看| 国产成人av网| 91精品久久久久久久久中文字幕| 77777少妇光屁股久久一区| 亚洲国产精品人人爽夜夜爽| 91精品国产91久久久久久最新| 91精品国产精品| 伊人精品在线观看| 欧美激情国产精品| 国产午夜精品美女视频明星a级| 国产成+人+综合+亚洲欧美丁香花| 久久久久久久97| 亚洲午夜未删减在线观看| 国产欧美精品一区二区| 日韩精品视频免费专区在线播放| 国内精品美女av在线播放| 国内精品久久久久久久| 奇门遁甲1982国语版免费观看高清| 欧美最顶级的aⅴ艳星| 国产一区二区三区在线看| 国产精品欧美一区二区| 国产香蕉一区二区三区在线视频| 影音先锋欧美在线资源| 国产精品福利小视频| 国产精品jizz在线观看麻豆| 免费av在线一区| 亚洲精品中文字| 亚洲欧美激情精品一区二区| 亚洲二区在线播放视频| 国产精自产拍久久久久久蜜| 啊v视频在线一区二区三区| 欧美视频国产精品| 亚洲精品日韩激情在线电影| 一本一道久久a久久精品逆3p| 日韩欧美国产黄色| 国产精品91久久久| 国产精品美女免费看| 欧美日韩国产精品一区二区不卡中文| 在线观看日韩专区| 91av在线播放视频| 亚洲人精品午夜在线观看| 久久久亚洲影院你懂的| 日韩精品视频观看| 97视频免费在线看| 成人在线视频网站| 日韩精品视频在线| 欧美一级电影免费在线观看| 成人激情在线观看| 伊人久久免费视频| 亚洲精品国精品久久99热一| 亚洲欧美中文另类| 亚洲一区av在线播放| 日韩在线免费av| 91在线视频导航| www.日韩.com| 成人有码视频在线播放| 久久艳片www.17c.com| 欧美激情xxxx| 亚洲高清免费观看高清完整版| 久久久久北条麻妃免费看| 91美女片黄在线观| 亚洲一区二区三| 成人av.网址在线网站| 日韩在线www| 欧美一级在线播放| 日韩在线免费视频| 欧美成人精品激情在线观看| 国产精品6699| 国产精品永久在线| 午夜免费久久久久| 91在线中文字幕| 久国内精品在线| 久久久精品欧美| 国产91精品久久久久久| 欧美视频在线免费| 国产男女猛烈无遮挡91| 亚洲电影免费观看高清完整版在线观看| 亚洲大尺度美女在线| 久久视频国产精品免费视频在线| 国内精品小视频在线观看| 亚洲精品久久久久中文字幕欢迎你| 日韩欧美在线国产| 亚洲无av在线中文字幕| 自拍偷拍亚洲区| 蜜臀久久99精品久久久久久宅男| 色综合久久悠悠| 这里只有精品久久| 九九九久久久久久| 欧美国产日韩xxxxx| 亚洲欧美三级伦理| 2018中文字幕一区二区三区| 久久久久久国产精品美女| 亚洲精品国产suv| 青青久久av北条麻妃海外网| 精品视频偷偷看在线观看| 欧美三级欧美成人高清www| 韩国国内大量揄拍精品视频| 日韩视频中文字幕| 中文字幕精品在线视频| 日韩电影在线观看中文字幕| 91a在线视频| 亚洲成人在线网| 91wwwcom在线观看| 在线视频中文亚洲| 久久久久久这里只有精品| 欧美华人在线视频| 精品视频久久久| 亚洲码在线观看| 性色av香蕉一区二区| 91精品啪aⅴ在线观看国产| 国产不卡av在线免费观看| 国产日韩欧美日韩| 日韩av影视在线| 国产一区视频在线| 高跟丝袜一区二区三区| 亚洲色图五月天| 欧美极品美女视频网站在线观看免费| 国产香蕉一区二区三区在线视频| 欧美激情图片区| 中文字幕免费精品一区| 一区二区三区黄色| 亚洲成人久久网| 欧美成在线视频| 欧美区在线播放| 91夜夜未满十八勿入爽爽影院| 亚洲综合视频1区| 国产精品久久久久99| 韩国视频理论视频久久| 日韩欧美中文第一页| 91久久国产综合久久91精品网站| 久久国产精品免费视频| 亚洲精品欧美一区二区三区| 欧美日韩国产一区二区| 成人淫片在线看| 欧美日韩亚洲一区二区三区| 亚洲人成网站777色婷婷| 欧美午夜影院在线视频| 亚洲美女免费精品视频在线观看| 992tv在线成人免费观看| 久久影视电视剧免费网站| 国产成人精品亚洲精品| 在线观看国产精品淫| 日韩av免费网站| 亚洲成人教育av|