尽管基数为空,为啥多重继承会增加对象的大小?

Posted

技术标签:

【中文标题】尽管基数为空,为啥多重继承会增加对象的大小?【英文标题】:Why does multiple inheritance increase the size of the object despite the bases being empty?尽管基数为空,为什么多重继承会增加对象的大小? 【发布时间】:2017-03-14 02:21:13 【问题描述】:

鉴于此代码:

#include <iostream>

struct A 

;

struct B 

;

struct C 

;

struct E : A 
    int field;
;

struct F : A, B 
    int field;
;

struct G : A, B, C 
    int field;
;

int main() 
    std::cout << _MSC_VER << std::endl;
    std::cout << sizeof(E) << std::endl;
    std::cout << sizeof(F) << std::endl;
    std::cout << sizeof(G) << std::endl;
    int o;
    std::cin >> o;
    return 0;

我得到以下输出:

1900
4
8
8

为什么FG 的大小是8,即使它们的基数是空的? 为什么E 的大小也不会增加?

我正在使用 Visual Studio Community 2015 版本 14.0.25431.01 Update 3 构建它。MSVC++ 版本显然是 9.0。

怎么会?如此奇特的内存布局有什么理由?

【问题讨论】:

为什么它应该是一个错误?你认为编译器违反了哪种语言规则? @KerrekSB 也许是“你不为你不使用的东西付费”的非正式规则。虽然它不在标准中,但如果我认为它被违反了,我会担心。 有一天你会长大,可以自己买东西,better compiler :-) 我用 clang 和 g++ 编译它,两种情况下的输出都是 4 4 4。所以它必须特定于 Visual c++。正如其他人所提到的,这不是一个错误,它只是编译器的一个选择。 也许 OP 应该删除“这可能是编译器错误”语句,这样人们就可以专注于“怎么来”部分。 【参考方案1】:

没有语言规则规定任何特定类型需要具有任何特定大小,char (大小 1)除外,并且受制于类类型的完整对象具有非零大小的约束。您的特定编译器在示例中布置类型的方式没有任何问题。

至于新问题,在您对其进行编辑后:MSVC 可能只是没有在优化多重继承方面投入大量精力,因为这是一件相对罕见的事情,您可以争辩说没有什么回报。我对正在进行的真正决策过程一无所知,但请考虑一下可能存在这样的务实工程权衡。

【讨论】:

随着C++/WinRT 的引入,对空基类优化的需求已经恢复。它从 Visual Studio 2015 Update 2 开始可用,但默认情况下它是关闭的(就像所有破坏二进制兼容性的更改一样)。【参考方案2】:

Visual Studio 2015 Update 2 添加了对空基类优化的支持。但是,由于更新应该是它们之间的布局兼容,因此默认情况下优化是不开启的;您需要使用 __declspec(empty_bases) 手动请求它。

VC 的博客中有更多信息: https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/

一旦他们发布主要编译器版本更新,这最终将成为默认设置,允许他们破坏二进制兼容性。

【讨论】:

以上是关于尽管基数为空,为啥多重继承会增加对象的大小?的主要内容,如果未能解决你的问题,请参考以下文章

为啥大多数编程语言不支持多重继承?

为啥要使用接口,多重继承与接口,接口的好处?

为啥我不能在多重继承期间动态转换“sideways”?

多重继承及虚继承中对象内存的分布

为啥在多重继承的情况下QObject需要是第一个

C++--被遗弃的多重继承经典问题