快速做網(wǎng)站的軟件免費(fèi)網(wǎng)絡(luò)空間搜索引擎
struct和union的對(duì)比
union最開始是C語言中的關(guān)鍵字,在嵌入式中比較常見,由于嵌入式內(nèi)存比較稀缺,所以常用union用來節(jié)約空間,在其他需要節(jié)省內(nèi)存的地方也可以用到這個(gè)關(guān)鍵字,寫一個(gè)簡單程序來說明union的用途
struct:
寫一個(gè)最簡單的struct結(jié)構(gòu)體:
struct S
{int i;double d;char c;
};
int main()
{S s;cout<<sizeof s<<endl;
}
最后得到結(jié)果為24
int占4位,double占8位,c占1位
由于內(nèi)存對(duì)齊的原因,最后用了3*8 = 24字節(jié)
?其在內(nèi)存布局如下:
union:
將這個(gè)結(jié)構(gòu)體改為union類型:
union U
{int i;double d;char c;
};
int main()
{U u;cout<<sizeof u<<endl;
}
最后輸出結(jié)果為8
union的三個(gè)變量公用一段內(nèi)存,所以同時(shí)只能存儲(chǔ)一個(gè)變量
其內(nèi)存布局如下:
讀取值得本質(zhì)是取到add,按照不同方式進(jìn)行讀取,類似于下面的代碼
u.i =(int)(*add);
u.d = (double)(*add);
u.c = (c)(*add);
union中的string
將編譯條件改為-std=c++03:
union U
{int i;double d;string s;
};
會(huì)發(fā)現(xiàn)不支持使用string?
因?yàn)閟tring不屬于POD對(duì)象,有構(gòu)造函數(shù),為了和C語言兼容,所以在舊版中禁止了在union中使用非POD對(duì)象(POD全稱是PlainOldData,簡單理解就是原來在C語言中的原生結(jié)構(gòu)體一類的,不帶構(gòu)造函數(shù)等)
不過在后面的C++版本中取消了這個(gè)限制
將編譯條件改為-std=c++11,編譯通過,所以在后面可以在union中使用帶構(gòu)造方法的對(duì)象了;
執(zhí)行如下例子:
#include <iostream>
#include <string>using namespace std;union U
{U(int i){_i = i;}U(string s){_s = s;}string _s;int _i;
};int main()
{U *u =new U("hello");cout<<u->_s<<endl;
}
輸出正常結(jié)果:
然而這里有一個(gè)問題:
這個(gè)對(duì)象是無法析構(gòu)的!!!
union中手動(dòng)添加析構(gòu)函數(shù)及使用析構(gòu)函數(shù)中的陷阱
加上析構(gòu)函數(shù):
int main()
{U *u =new U("hello");cout<<u->_s<<endl;delete u;
}
直接報(bào)錯(cuò):
這時(shí)候,加上析構(gòu)函數(shù)釋放內(nèi)存就可以了:
~U(){_s.~string();}
這樣就可以在union中使用string等非POD對(duì)象了
但是會(huì)出現(xiàn)一個(gè)比較大的陷阱,當(dāng)這個(gè)union中存的不為string的時(shí)候
int main()
{U *u =new U(12);delete u;
}
這時(shí)候調(diào)用delete u時(shí),~U()的~string()就會(huì)出錯(cuò)(對(duì)著一個(gè)int類型使用string的析構(gòu)):
這就需要另外處理了,比如判空
~U(){if(!_s.empty(){_s.~string();}}