2013-03-23 51 views
0

The "Empty Member" C++ Optimization是下面的代碼片斷:爲什麼分配器接口封裝的「列表」實現的嵌套類也受益於封裝節點?

// Listing 4: A Better Way to Eliminate Bloat 

template <class T, class Alloc = allocator<T> > 
class list { 
    . . . 
    struct Node { . . . }; 
    struct P : public Alloc { 
    P(Alloc const& a) : Alloc(a), p(0) { } 
    Node* p; // Why also encapsulate a Node pointer? 
    }; 
    P head_; 

public: 
    explicit list(Alloc const& a = Alloc()) 
    : head_(a) { . . . } 
    . . . 
}; 

這個實現的目的主要是避免對象膨脹以防Alloc類沒有任何數據成員(如在默認allocator類),但是一個重要的注意此特定實施的好處是可以防止(任意的)類別和list類別的成員之間的潛在名稱衝突。

的代碼片段下方的註釋通過陳述總結了以下幾點:

現在,名單<>成員說「head_.allocate()」獲得存儲和 說提第一個列表元素「head_.p」。這工作 完美,沒有任何不必要的開銷,並且 列表<>的用戶無法區分差異。

我明白這個評論的第一部分,即P類中的接口封裝,使list<>成員必須調用head_.allocate()獲得存儲。

不過,我不明白這個評論的第二部分 - 爲什麼它是必要的(或有益),包括在PNode指針,以便list<>成員說head_.p(而不是僅僅有提第一個列表元素p直接成爲list<>的成員)?這與封裝Alloc類的接口有關嗎?

爲什麼接口封裝嵌套類具有指向Node而不是頂級類的指針?

回答

2

在這種情況下,sizeof(list)將爲sizeof(P),而這又有望爲sizeof(Node*)。如果Alloc類型爲空,則會優化其空間使用情況。

現在考慮下面的選擇。

class list { 
    struct Node { . . . }; 
    struct P : public Alloc { 
    P(Alloc const& a) : Alloc(a), p(0) { } 
    }; 
    Node* head_pointer; 
    P thing_with_allocator; 
} 

在這種情況下,sizeof(list)sizeof(Node*) + sizeof(P)。空基類優化在這裏並不能真正起到幫助作用,因爲即使P現在是一個空類,它也不會作爲基礎使用,因此它不能進行空基類優化:它的大小至少爲1.

1

你會選擇什麼?

class list { 
    struct P : public Alloc { 
     P(Alloc const& a) : Alloc(a), p(0) { } 
    }; 
    P a; 
    Node* h; 
    ... 
}; 

那麼你就不會因爲你已經有實例化一個潛在的零大小P對象保存任何東西。這將佔用您的列表對象中至少一個字節。