程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 空基類優化EBO之深度探索

空基類優化EBO之深度探索

編輯:關於C語言

 一、EBO的背景
   我們知道一個空的類,也就是其內部沒有非靜態數據成員,沒有虛指針(包括指向虛函數表和虛基類子對象的指針),它的大小通常為1,當然在某些對齊要求嚴格系統上可能是另一個數(通常是4),如果空類被繼承,那麼派生類的大小會怎麼樣呢?一個支持C++標准和EBO的編譯器對此會進行空基類的優化,也就是不給空的基類子對象分配空間,換句話說,空基類子對象的地址和其派生類實例的地址是相同的。從編譯器實現的角度來看,需要考慮繼承時的不同情況,下圖中P表示父類,C表示子類,圓形表示空類,矩形表示非空類。單繼承EBO情況如下圖所示 

\

   EBO-1反映的是空類派生自空基類,EBO-2反映的是非空類派生自空基類,EBO-3、EBO-4反映的是在繼承鏈中,對空基類的優化能不能傳遞到後代中。多繼承EBO如下圖所示

\
   EBO-5反映的是空類派生自兩個空基類,EBO-6反映的是非空類派生自兩個空基類,EBO-6反映的是空類派生自一個非空基類和一個空基類,EBO-7反映的是非空類派生自一個非空基類和一個空基類。以上8種情況,不論是單繼承還是多繼承,一個完全支持EBO的編譯器就應該能把空基類部分都優化掉。

   二、EBO的應用
   由於空基類優化技術節省了對象不必要的空間,提高了運行效率,因此成為某些強大技術的基石,基於類型定義類如stl中的binary_function、unary_function、iterator、iterator_traits的實現復用;基於策略類如內存管理、多線程安全同步的實現復用。當某個類存在空類類型的數據成員時,也可考慮借助EBO優化對象布局,代碼描述如下
1template<typename T1,typename T2>
2class EBO
3{
4private:
5    T1 m_t1;
6    T2 m_t2;
7};
   當T1和T2為空類時,可以改進如下

1template<typename T1,typename T2>
2class EBO : T1, T2
3{
4};
   進一步擴展考慮,如果T1或T2為非類類型,如基本內建類型、函數指針等;或T1和T2類型相同時,則直接繼承它們會導致編譯錯誤,怎麼辦呢?這時可以添加一個中間層來解決,代碼如下
 1template<typename T1,typename T2,bool isSame,bool isFirstEmpty,bool isSecondEmpty>
 2class EBO_IMPL;
 3
 4template<typename T1,typename T2>
 5class EBO_IMPL<T1,T2,false,false,false>
 6{
 7    T1 m_t1;
 8    T2 m_t2;
 9};
10
11template<typename T1,typename T2>
12class EBO_IMPL<T1,T2,false,true,true> : T1,T2
13{
14};
15
16template<typename T1,typename T2>
17class EBO_IMPL<T1,T2,false,true,false> : T1
18{
19    T2 m_t2;
20};
21
22template<typename T1,typename T2>
23class EBO_IMPL<T1,T2,false,false,true> : T2
24{
25    T1 m_t1;
26};
27
28template<typename T1,typename T2>
29class EBO_IMPL<T1,T2,true,false,false>
30{
31    T1 m_t1;
32    T2 m_t2;
33};
34
35template<typename T1,typename T2>
36class EBO_IMPL<T1,T2,true,true,true> : T1
37{
38    T2 m_t2;
39};
40
41template<typename T1,typename T2>
42class EBO : EBO_IMPL<T1,T2,boost::is_same<T1,T2>::value,boost::is_empty<T1>::value,boost::is_empty<T2>::value>
43{
44};
   為了簡便實現,上面代碼直接使用了boost中的is_same,is_empty元函數來判斷類型的屬性,實際上boost中已經實現了EBO的選擇運用工具即compressed_pair類模板,研究其源碼可發現,該工具充分考慮到了T1和T2實際類型的各種情況,is_empty的判斷是運用sizeof來比較類型大小確定的。替換compressed_pair後,代碼如下
1template<typename T1,typename T2>
2class EBO: boost::compressed_pair<T1,T2>
3{
4};

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved