3

.

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

任何类都不能有 sizeof(Class)==0,无论是否为空。但是我们专门讨论的是空基类子对象的大小。 它不需要自己的 vtable,也不需要 vtable 指针。假设一个 vtable 指针在偏移量 0 处的通用布局;这将导致零大小的基类子对象与派生类共享其 vtable 指针。没问题:无论如何,它们应该是相同的,这几乎就是虚函数的重点。

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

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

.

4

3 回答 3

4

很好的答案。

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

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

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

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

快乐黑客!

于 2010-12-02T20:16:45.690 回答
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>))
于 2010-12-02T19:54:00.930 回答
0

你不能。sizeof()作为基准时,实际大小可能与信息有很大差异。

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

于 2010-12-02T19:32:59.523 回答