C++中的Union

來源:互聯網
上載者:User

  我們應該按照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時會有什麼不同。看看下面的程式,並請注意閱讀程式提示:

  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還是可以的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.