0

空のメンバー」の C++ 最適化は、次のコード スニペットです。

// 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が、この特定の実装の重要な注目すべき利点は、(任意の)Allocクラスとlistクラスのメンバー。

コード スニペットの下のコメントには、次のように要約されています。

これで、list<> メンバーは「head_.allocate()」と言ってストレージを取得し、「head_.p」と言って最初のリスト要素に言及します。これは完全に機能し、不必要なオーバーヘッドは一切なく、list<> のユーザーには違いがわかりません。

このコメントの最初の部分、つまり、メンバーがストレージを取得するために呼び出す必要があるPクラス内のインターフェイスのカプセル化を理解しています。list<>head_.allocate()

しかし、私はこのコメントの2番目の部分を理解していません.クラスにNodeポインタを含める必要がある(または有益な)のはなぜですか? これは、クラスのインターフェイスをカプセル化することに関連していますか?Plist<>head_.pplist<>Alloc

Nodeインターフェイスをカプセル化するネストされたクラスに、最上位クラスではなくへのポインタがあるのはなぜですか?

4

2 に答える 2

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です。

于 2013-03-23T20:18:01.223 に答える
1

あなたの代替手段は何ですか?

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

Pサイズがゼロの可能性のあるオブジェクトをインスタンス化する必要があったため、何も保存されませんでした。これは、リスト オブジェクトで少なくとも 1 バイトを占めます。

于 2013-03-23T20:15:39.170 に答える