基本上它是this question的跟进 ..
当我查看标准文档时,我发现了这个..
在类9.3 ,
中类类型的完整对象和成员子对象应具有非零大小。 96) ...
是的,是的..但是,
96)基类子对象不受约束。
所以,当我查看Stroustrup's FAQ时,有一个例子为
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << "nice: good optimizer";
}
我的问题是我无法理解如何进行优化以及为什么基类允许零大小?
答案 0 :(得分:11)
基类 不能 的大小为零。只有基类 子对象 才可以。表示派生对象的基本部分。
答案 1 :(得分:10)
如果基类为空,则永远不需要拥有基类对象或其任何成员的地址(独立于派生类对象的地址),因此优化其大小是合法的。
这可以节省你(至少)一个字节的内存(可能更多是由于内存对齐规则),如果你的应用程序在内存受限的平台上有数百万个这样的对象,这可以大大节省成本。 / p>
答案 2 :(得分:0)
我不是雷蒙德·陈,但我可以玩'如果它是真的'游戏。
如果可以作为引用传递的类可以是零大小,那么在某些时候它可能会传递给malloc(0)
,这可能会返回NULL或不可解析的地址。然后两个实例在不应该的时候看起来相等。
如果它是另一个类或基类的成员,它的地址和大小是从它在包含类分配中的位置得出的,并且它的大小是安全的。
零大小有助于提高内存效率。
答案 3 :(得分:0)
这是一种优化,因为如果基类子对象需要具有非零大小,则派生类的实例占用的空间比它们所占用的空间少。这意味着基类(如接口,混合或模板化策略类)不会增加实现或使用它们的类的大小。最终,你的程序需要更少的内存来做同样的事情。
我对历史并不十分肯定,但我得到的印象是,在20世纪90年代的某个时候,一些编制者开始这样做,标准委员会决定将现有做法标准化。我认为STL模板中分配器对象的增加是原因的一部分 - std::vector
通常是具有空基优化的3个指针的大小,而没有它的4个指针(由于对齐)。 Here's an article从1997年开始讨论它 - 很明显,当它写成时并不是那么普遍,但它现在基本上是标准的做法。
答案 4 :(得分:0)
对象的大小只不过是其成员的累积大小。 并且不,没有类可以具有零大小,即使空类也将具有1字节的大小。
这里的意思是
Base class subobjects are not so constrained.
是对象本身不会消耗任何空间而不是它的成员。因此,对象的地址可能与其第一个成员子对象的地址匹配,与arrays
的情况相同。那就是优化。
在派生类的情况下,它必然包括基类对象,即使为空也会消耗1个字节,因此上面的优化对派生类无效。