這段時(shí)間整理舊資料,看到一些文章,雖然講的都是些小問題,不大可能用到,但也算是一個(gè)知識(shí)點(diǎn),特整理出來與大家共享。與此相關(guān)的那篇文章的作者的有些理解是錯(cuò)誤的,我寫此文,也是糾正為了作者的一些錯(cuò)誤認(rèn)識(shí)。當(dāng)然,如果我的理解有任何錯(cuò)誤,也懇請(qǐng)大家批評(píng)指正。
C++雖說被B.S.稱作一門新語言,但它畢竟與C有著千絲萬縷的聯(lián)系,雖然B.S.一再堅(jiān)持,但我還是愿意把C++看作是C ++。
我們應(yīng)該按照C中的convention去使用union,這是我這篇文章要給出的觀點(diǎn)。雖然C++使得我們可以擴(kuò)展一些新的東西進(jìn)去,但是,我建議你不要那樣去做,看完這篇文章之后,我想你大概也是這么想的。
C由于沒有類的概念,所有類型其實(shí)都可以看作是基本類型的組合,因此在union中包含struct也就是一件很自然的事情了,到了C++之后,既然普遍認(rèn)為C++中的struct與class基本等價(jià),那么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
而如果去掉那個(gè)什么也沒干的構(gòu)造函數(shù),則一切OK。
為什么編譯器不允許我們的union成員有構(gòu)造函數(shù)呢?我無法找到關(guān)于這個(gè)問題的比較權(quán)威的解釋,對(duì)這個(gè)問題,我的解釋是:
如果C++標(biāo)準(zhǔn)允許我們的union有構(gòu)造函數(shù),那么,在進(jìn)行空間分配的時(shí)候要不要執(zhí)行這個(gè)構(gòu)造函數(shù)呢?如果答案是yes,那么如果TestUnion的構(gòu)造函數(shù)中包含了一些內(nèi)存分配操作,或者其它對(duì)整個(gè)application狀態(tài)的修改,那么,如果我今后要用到obj的話,事情可能還比較合理,但是如果我根本就不使用obj這個(gè)成員呢?由于obj的引入造成的對(duì)系統(tǒng)狀態(tài)的修改顯然是不合理的;反之,如果答案是no,那么一旦我們今后選中了obj來進(jìn)行操作,則所有信息都沒有初始化(如果是普通的struct,沒什么問題,但是,如果有虛函數(shù)呢?)。更進(jìn)一步,假設(shè)現(xiàn)在我們的union不是只有一個(gè)TestUnion obj,還有一個(gè)TestUnion2 obj2,二者均有構(gòu)造函數(shù),并且都在構(gòu)造函數(shù)中執(zhí)行了一些內(nèi)存分配的工作(甚至干了很多其它事情),那么,如果先構(gòu)造obj,后構(gòu)造obj2,則執(zhí)行的結(jié)果幾乎可以肯定會(huì)造成內(nèi)存的泄漏。
鑒于以上諸多麻煩(可能還有更多麻煩),在構(gòu)造union時(shí),編譯器只負(fù)責(zé)分配空間,而不負(fù)責(zé)去執(zhí)行附加的初始化工作,為了簡化工作,只要我們提供了構(gòu)造函數(shù),就會(huì)收到上面的error。
C++雖說被B.S.稱作一門新語言,但它畢竟與C有著千絲萬縷的聯(lián)系,雖然B.S.一再堅(jiān)持,但我還是愿意把C++看作是C ++。
我們應(yīng)該按照C中的convention去使用union,這是我這篇文章要給出的觀點(diǎn)。雖然C++使得我們可以擴(kuò)展一些新的東西進(jìn)去,但是,我建議你不要那樣去做,看完這篇文章之后,我想你大概也是這么想的。
C由于沒有類的概念,所有類型其實(shí)都可以看作是基本類型的組合,因此在union中包含struct也就是一件很自然的事情了,到了C++之后,既然普遍認(rèn)為C++中的struct與class基本等價(jià),那么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
而如果去掉那個(gè)什么也沒干的構(gòu)造函數(shù),則一切OK。
為什么編譯器不允許我們的union成員有構(gòu)造函數(shù)呢?我無法找到關(guān)于這個(gè)問題的比較權(quán)威的解釋,對(duì)這個(gè)問題,我的解釋是:
如果C++標(biāo)準(zhǔn)允許我們的union有構(gòu)造函數(shù),那么,在進(jìn)行空間分配的時(shí)候要不要執(zhí)行這個(gè)構(gòu)造函數(shù)呢?如果答案是yes,那么如果TestUnion的構(gòu)造函數(shù)中包含了一些內(nèi)存分配操作,或者其它對(duì)整個(gè)application狀態(tài)的修改,那么,如果我今后要用到obj的話,事情可能還比較合理,但是如果我根本就不使用obj這個(gè)成員呢?由于obj的引入造成的對(duì)系統(tǒng)狀態(tài)的修改顯然是不合理的;反之,如果答案是no,那么一旦我們今后選中了obj來進(jìn)行操作,則所有信息都沒有初始化(如果是普通的struct,沒什么問題,但是,如果有虛函數(shù)呢?)。更進(jìn)一步,假設(shè)現(xiàn)在我們的union不是只有一個(gè)TestUnion obj,還有一個(gè)TestUnion2 obj2,二者均有構(gòu)造函數(shù),并且都在構(gòu)造函數(shù)中執(zhí)行了一些內(nèi)存分配的工作(甚至干了很多其它事情),那么,如果先構(gòu)造obj,后構(gòu)造obj2,則執(zhí)行的結(jié)果幾乎可以肯定會(huì)造成內(nèi)存的泄漏。
鑒于以上諸多麻煩(可能還有更多麻煩),在構(gòu)造union時(shí),編譯器只負(fù)責(zé)分配空間,而不負(fù)責(zé)去執(zhí)行附加的初始化工作,為了簡化工作,只要我們提供了構(gòu)造函數(shù),就會(huì)收到上面的error。

