C ++:我怎么知道Base类SubObject的大小?

时间:2010-12-02 19:27:46

标签: c++ class compiler-construction abstract-class compiler-optimization

Here我在讨论空基优化,MSalters发表了这个有趣的评论:

  

没有班级可以拥有   sizeof(Class)== 0,空或不。的但   我们专门谈论   空基类子对象的大小。   它不需要自己的vtable,也不需要   vtable指针。假设共同点   偏移处的vtable指针的布局   0;这将导致零大小   基类子对象分享它   vtable指针与派生类。   没问题:那些应该是相同的   无论如何,这就是重点   虚函数。

我的问题具体是这样的:当我们使用Empty Class作为基类时,编译器可能会优化,或者它可能不会。我们如何确定它实际上做了什么?

一般来说,我们如何知道基类子对象的大小? Base子对象的大小是否相同,无论我们是否使用它作为基础?编译器是否仅使用空基类进行优化?

3 个答案:

答案 0 :(得分:4)

好的答案。

顺便说一句,MS VC ++和G ++编译器可以转储类布局供你学习。

使用VC ++运行cl.exe /c /d1reportAllClassLayout <source>.cpp

这使用我在1990年写的类和vtable布局转储代码来测试正确的布局对象,vtable,vbtables等。

为了更好地理解C ++编译器如何在内存中布置对象,您可能会喜欢http://www.openrce.org/articles/files/jangrayhood.pdf和Stan Lippman的书“Inside the C ++ Object Model”。

快乐的黑客攻击!

答案 1 :(得分:2)

对象的最小尺寸为1:

class X {};
sizeof(X) >= 1

但如果未使用派生类,则不需要为此空间分配空间:

class Y : public X {};
sizeof(Y) >= 1

因此即使类X本身占用1个字节,也不会转换为父类。所以从Y的角度来看,类X占用0个字节。

所以在这里我们可以说编译器已经优化了基类(虽然从技术上讲它没有做任何事情。我们只需要强制执行没有对象零大小的规则。)

int main()
{
    std::cout << sizeof(X) << ":" << sizeof(Y) << "\n";
}

生成以下输出:

> ./a.exe
1:1
>

类的大小必须大于零的原因是每个对象的地址都是唯一的。如果编译器允许类具有零大小,则存在潜在的容易错误,其中多个变量(对象)都具有相同的存储器地址(因为它们都具有零大小)。解决这个潜在问题的简单规则是所有对象必须具有非零大小。

要点:

size_of_type(X) = size_of_type(base) + sum(size_of_type(members)) + padding + (extra stuff like vtable pointer etc);


sizeof(<CLASS>) = min(1, size_of_type(<CLASS>))

答案 2 :(得分:0)

你做不到。作为基础时,实际大小可能与sizeof()信息有很大不同。

除EBO之外的另一个例子是虚拟继承。