最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++聯(lián)合體union用法實例詳解

 更新時間:2015年05月26日 09:44:03   作者:巫祝  
這篇文章主要介紹了C++聯(lián)合體union用法,較為詳細的分析了C++中聯(lián)合體的概念、實用技巧及相關注意事項,需要的朋友可以參考下

本文實例講述了C++聯(lián)合體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

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

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

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

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

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

  此外,如果我們的類中包含了任何virtual函數(shù),編譯時,我們將收到如下的錯誤信息:
  error C2621: union '__unnamed' : member 'obj' has copy constructor

  所以,打消在union中包含有構造函數(shù)/析構函數(shù)/拷貝構造函數(shù)/賦值運算符/虛函數(shù)的類成員變量的念頭,老老實實用你的C風格struct吧!
  不過,定義普通的成員函數(shù)是OK的,因為這不會使得class與C風格的struct有任何本質區(qū)別,你完全可以將這樣的class理解為一個C風格的struct + n個全局函數(shù)。

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

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也可以包含構造函數(shù),但是,這雖然被語言所支持,但實在是一種不佳的編程習慣,因此,        我不打算對上面的程序進行過多的說明。我更推薦如下的編程風格:

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];
      };
    };
};

 這樣我們既可以根據(jù)具體的含義來訪問變量,也可以象數(shù)組一樣的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位機上,只要一次,或者傳輸數(shù)據(jù)的情況,壓縮解壓縮都非常方便;

3. 危險:

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

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

1、什么是聯(lián)合?

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

2、聯(lián)合與結構的區(qū)別?

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

下面舉一個例了來加對深聯(lián)合的理解。

例4:

#include <stdio.h>
void main()
{
  union number
  { /*定義一個聯(lián)合*/
   int i;
   struct
   { /*在聯(lián)合中定義一個結構*/
    char first;
    char second;
   }half;
  }num;
  num.i=0x4241; /*聯(lián)合成員賦值*/
  printf("%c%c\n", num.half.first, num.half.second);
  num.half.first='a'; /*聯(lián)合中結構成員賦值*/
  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的聯(lián)合類型,它含有兩個成員,一個為整型,成員名office;另一個為字符數(shù)組,數(shù)組名為teacher。聯(lián)合定義之后,即可進行聯(lián)合變量說明,被說明為test類型的變量,可以存放整型量office或存放字符數(shù)組teacher。

4、如何說明?

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

以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數(shù)組的長度,共5個字節(jié)。a,b變量如賦予整型值時,只使用了4個字節(jié),而賦予字符數(shù)組時,可用5個字節(jié)。

5、如何使用?

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

6、匿名聯(lián)合

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

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

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

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

1)聯(lián)合里面那些東西不能存放?

我們知道,聯(lián)合里面的東西共享內存,所以靜態(tài)、引用都不能用,因為他們不可能共享內存。

2)類可以放入聯(lián)合嗎?

我們先看一個例子:

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

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

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對象時發(fā)生了什么,當創(chuàng)建test對象時,自然要調用其相應的構造函數(shù),在構造函數(shù)中當然要調用其成員的構造函數(shù),所以其要去調用datatype成員的構造函數(shù),但是他沒有構造函數(shù)可調用,所以出
錯。
注意了,這里可并不是匿名聯(lián)合!因為它后面緊跟了個data!

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

使用聯(lián)合可以節(jié)省內存空間,但是也有一定的風險:通過一個不適當?shù)臄?shù)據(jù)成員獲取當前對象的值!例如上面的ch、i交錯訪問。

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

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

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

相關文章

  • C語言中條件判斷的正確使用姿勢

    C語言中條件判斷的正確使用姿勢

    在C語言中,有三種條件判斷結構:if語句、if-else語句和switch語句,這篇文章主要來和大家講解一下它們的正確使用姿勢,需要的可以參考一下
    2023-05-05
  • C++17中的std::from_chars函數(shù)使用及說明

    C++17中的std::from_chars函數(shù)使用及說明

    這篇文章主要介紹了C++17中的std::from_chars函數(shù)使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-10-10
  • 使用C語言實現(xiàn)字符串逆序操作案例

    使用C語言實現(xiàn)字符串逆序操作案例

    這篇文章主要介紹了使用C語言實現(xiàn)字符串逆序操作案例,本文包含使用C語言的兩種方法去實現(xiàn),遞歸和非遞歸,以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • C++ string類getline()用法實例詳解

    C++ string類getline()用法實例詳解

    C++ getline()是一種標準庫函數(shù),用于從輸入流中讀取字符串或行,它是<string>標頭的一部分,本文介紹C++ string類getline()用法詳解,感興趣的朋友一起看看吧
    2024-03-03
  • c++11?類中關于default、explict、implicit、noexcept、final的詳解

    c++11?類中關于default、explict、implicit、noexcept、final的詳解

    這篇文章主要介紹了c++11?類中關于default、explict、implicit、noexcept、final的詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Windows平臺下配置VS Code的C++環(huán)境教程

    Windows平臺下配置VS Code的C++環(huán)境教程

    這篇文章主要介紹了Windows平臺下配置VS Code的C++環(huán)境教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • C++ decltype類型說明符

    C++ decltype類型說明符

    在C++中,decltype作為操作符,用于查詢表達式的數(shù)據(jù)類型。decltype在C++11標準制定時引入,主要是為泛型編程而設計,以解決泛型編程中,由于有些類型由模板參數(shù)決定,而難以(甚至不可能)表示之的問題。
    2016-03-03
  • C++11?中的override詳解

    C++11?中的override詳解

    這篇文章主要介紹了C++11?中的override詳解,本文以重寫虛函數(shù)時,容易犯的四個錯誤為例,結合示例代碼給大家詳細介紹,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • C語言?超詳細講解鏈接器

    C語言?超詳細講解鏈接器

    在C語言中,一個重要的思想就是分別編譯,即若干個源程序能夠在不一樣的時候單獨進行編譯,而后在恰當?shù)臅r候整合到一塊兒??墒擎溄悠魍ǔJ桥cC編譯器分離的,鏈接器如何作到把若干個C源程序合并成一個總體呢,我們一起來看看
    2022-03-03
  • C語言實現(xiàn)用戶態(tài)線程庫案例

    C語言實現(xiàn)用戶態(tài)線程庫案例

    下面小編就為大家?guī)硪黄狢語言實現(xiàn)用戶態(tài)線程庫案例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05

最新評論

德清县| 黎平县| 文昌市| 西宁市| 长沙市| 南昌市| 澄江县| 富顺县| 农安县| 石棉县| 曲沃县| 获嘉县| 勐海县| 南宁市| 收藏| 宁阳县| 宁阳县| 黄梅县| 富宁县| 玛多县| 天台县| 孝感市| 绥宁县| 鲁山县| 鄄城县| 襄汾县| 纳雍县| 衡山县| 宝坻区| 独山县| 若羌县| 盐津县| 舒兰市| 瑞金市| 印江| 云林县| 会昌县| 吉木乃县| 剑河县| 沁源县| 金寨县|