C++ 中具有虚拟继承的类大小
#include<iostream>
using namespace std;
class abc
{
int a;
};
class xyz : public virtual abc
{
int b;
};
int main()
{
abc obj;
xyz obj1;
cout<<endl<<sizeof(obj);
cout<<endl<<sizeof(obj1);
return 0;
}
答案将取决于编译器,但当我看到结果时,我感到很惊讶
~/Documents/workspace/tmp ‹.rvm-› $ ./class_sizes
4
16
如果我删除 virtual 关键字,则分配的大小分别为 4 和 8,这正是我所期望的。
为什么额外的空间会被占用呢? 我怀疑它是用于 vptr 表或类似的东西,但不确定。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一篇关于 GCC 中的虚拟继承和多重继承的好文章 (互联网档案永久链接):
http://phpcompiler.org/articles/virtualinheritance.html
但它并不能完全回答你的问题,因为您从您正在使用的任何(未指定)编译器和构建设置中获得 20 个字节的输出。
如果您使用 GCC(至少在 IDEone 使用的默认设置下),那么您将获得 12 个字节。这与您编写的内容是一样的:
如果您在 abc 包含虚拟方法时虚拟地继承它:
...那么您将从 GCC 中获得 16 个字节。
如果我必须对您的 16 字节差异进行疯狂猜测:我可能会调查您的编译器的虚拟继承实现是否将所有虚拟基类视为具有虚拟方法,即使它们没有?
但我几乎弥补了这一点。如果你想检验这个理论,你就必须进一步深入研究。它依赖于实现。
A good article on virtual and multiple inheritance in GCC is this one (Internet Archive Permalink):
http://phpcompiler.org/articles/virtualinheritance.html
Yet it doesn't quite answer your question, as you are getting an output of 20 bytes out of whatever (unspecified) compiler and build settings you are using.
If you were using GCC (under the default settings IDEone uses, at least), then you would be getting 12 bytes. Which is the same thing as what it would give had you written:
Were you to virtually inherit from abc when it contains virtual methods:
...then you would get 16 bytes out of GCC.
If I had to make a wild guess about your 16 byte variance: I might look into if your compiler's implementation of virtual inheritance treats all virtual base classes as if they had virtual methods, even if they didn't?
But I pretty much made that up. You'll have to look further under the hood if you want to test the theory; it's implementation-dependent.
虚拟基类增加了(动态、运行时)转换要求,我认为大小增加是为了一种“旋转基础”,以便在执行时以明确的方式遍历(基)类层次结构这样的转换。
言归正传,这里有一个反例,可以显示正在发生的事情:
virtual abc
http://ideone.com/h5y7Rsizeof(xyz) == 44
(64 位架构上为 88)abc
http://ideone.com/h5y7Rsizeof(xyz) == 68
(64 位架构上的128(已填充)))
将
abc
基标记为虚拟基时(至少在 gcc 上),您会注意到大小显着减小。另外,请注意,将(任何)interm
editate 基类标记为(非)虚拟时不会产生任何影响。Virtual bases classes increase (dynamic, runtime) conversion requirements, and I suppose that the size increase are for a kind of 'pivoting ground' to walk the (base) class hierarchy in non-ambiguous ways when doing such conversions.
In less mumbo jumbo, here is a counter example that could show what's going on:
virtual abc
http://ideone.com/h5y7Rsizeof(xyz) == 44
(88 on 64bit arch)abc
http://ideone.com/h5y7Rsizeof(xyz) == 68
(128 (padded) on 64bit arch)You'll notice a significant reduction in size when marking the
abc
base as virtual (at least on gcc). Also, note no effect when marking (any) of theinterm
ediate base classes as (non)virtual.对于虚拟基类,基对象相对于派生对象实例的位置并不总是相同,因此有一个指针来跟踪它。
With virtual base classes, the position of the base object relative to an instance of the derived object is not always the same, so there is a pointer that tracks that.
非虚拟继承就像对象包含一样,给定:
它可以这样编译为 C++:
虚拟继承就像添加一个间接级别,给定
这可以编译为 C++,当
你明白的时候...
注意:我没有描述vtable指针成员。 (它可以用来代替
Base&
,以获得更小的类。)Non-virtual inheritance is just like object containment, given:
It can be compiled to C++ just this way:
Virtual inheritance is like adding a level of indirection, given
This can be compiled to C++ as
You get the idea...
Note: I have not described the vtable pointer member. (It can be used instead of the
Base&
, to have smaller classes.)该程序在 CodeBlocks Compiler 中运行时给出 4 12 作为输出
这可以解释为;对于基类,对象的大小等于 int 的大小。
对于派生类;对象的大小 = 类的大小 + 基类的大小 + 虚拟基指针的大小 (4)。
The program when run in CodeBlocks Compiler gives 4 12 as output
This can be explained as; for base class size of object is equal to size of int.
For derived class; size of object = size of the class + size if base class + size of virtual base pointer(4).