在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
类成员之间潜在的名称冲突。
代码段下方的评论通过声明以下内容对此进行了总结:
现在,列出&lt;&gt;成员通过说“head_.allocate()”得到存储,和 通过说“head_.p”提到第一个列表元素。这有效 完美的,没有任何不必要的开销和用户 列表&LT;&GT;分不清楚。
我理解此评论的第一部分,即P
类中的界面封装,以便list<>
成员必须调用head_.allocate()
来获取存储空间。
但是,我不理解此评论的第二部分 - 为什么在课程Node
中包含P
指针是必要的(或有益的),以便list<>
成员提及第一个列表元素是说head_.p
(而不仅仅是让p
成为list<>
的成员)?这是否封装了Alloc
类的接口?
为什么包含接口的嵌套类具有指向Node
的指针,而不是顶级类?
答案 0 :(得分: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。
答案 1 :(得分:1)
你的选择是什么?
class list {
struct P : public Alloc {
P(Alloc const& a) : Alloc(a), p(0) { }
};
P a;
Node* h;
...
};
然后你就不会保存任何东西,因为你必须实例化一个可能为零的P
对象。这将占用列表对象中至少一个字节。