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