c++ - 为什么分配器接口(interface)封装嵌套类的 "list"实现也受益于封装节点?

标签 c++ list optimization

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 类),但此特定实现的一个重要的值得注意的好处是防止(任意)Alloc 之间潜在的名称冲突类和 list 的成员类。

代码片段下方的评论通过以下说明对此进行了总结:

Now, list<> members get storage by saying "head_.allocate()", and mention the first list element by saying "head_.p". This works perfectly, there's no unnecessary overhead of any kind, and users of list<> can't tell the difference.

我理解了这个评论的第一部分,即P中的接口(interface)封装。上课所以list<>成员(member)必须调用head_.allocate()获取存储空间。

但是,我不明白此评论的第二部分 - 为什么有必要(或有益)包含 Node类中的指针 P这样list<>成员通过说 head_.p 来提及第一个列表元素(而不是让 p 直接成为 list<> 的成员)?这与封装Alloc的接口(interface)有关吗?类(class)?

为什么封装接口(interface)的嵌套类有一个指向Node的指针, 而不是顶级类?

最佳答案

在这种情况下,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。

关于c++ - 为什么分配器接口(interface)封装嵌套类的 "list"实现也受益于封装节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15591520/

相关文章:

c++ - 尽可能快地读取标准输入

c++ - 使用 move 语义优化二进制算术运算

c++ - 指针输出

C++11:lambda 捕获以什么顺序被破坏?

c++ - "use -D_SCL_SECURE_NO_WARNINGS"是什么意思?

python - 我怎样才能更好地编写这些函数以使其有意义

java - 如何使用Java中的流查找字符串列表中的最大长度?

c++ - Bin Packing 算法 - 实际变体

java - 如何将此 HTML 文本转换为 SQLite 数据库?

list - 串联前后的列表检查具有不同的结果