【问题标题】:why size of Class increases in some inconsistent(patterned) way when Virtual Inheritance is used?当使用虚拟继承时,为什么类的大小会以某种不一致(模式化)的方式增加?
【发布时间】:2021-07-05 15:20:56
【问题描述】:

这是我的理解:

在虚拟继承期间,:virtual base{} 派生类连同继承的数据成员必须保留 vpointer(以跟踪 base 的成员以保留单个成员实例),并且每个虚拟继承 base 的继承层次结构有一个 vpointer出现在derived 班级中。

在此代码中具有此知识:

  • sizeof(B) 和 sizeof(C) 应该是 = sizeof(A) + vptr
  • sizeof(D) 应该是 = sizeof(A) + vptr_from_B + vptr_from_C
struct A{
    int i=3,j=1,k=2;
};
struct B: virtual A{};
struct C: virtual A{};
struct D:B,C{};

int main()
{
    std::cout<<"size of class D = "<<sizeof(D)<<"\n";
    std::cout<<"size of class C = "<<sizeof(C)<<"\n";
    std::cout<<"size of class B = "<<sizeof(B)<<"\n";
    std::cout<<"size of class A = "<<sizeof(A)<<"\n";

    return 0;
}

案例1:

结构 A{};空结构

D = 16 , C = 8 , B = 8 , A = 1

案例2:

结构 A{ int i = 3; };一个整数

D = 24 , C = 16 , B = 16 , A = 4

  • 为什么 B、C 和 D 有额外的 4 个字节?

案例3:

结构 A{ int i = 3, j = 1; };两个整数

D = 24 , C = 16 , B = 16 , A = 8

  • 现在 B、C 和 D 的大小保持不变,即使 A 的 sizeof 增加了 4 个字节,...?

案例4:

结构 A{ int i = 3, j = 1, k = 2};三个整数

D = 32 , C = 24 , B = 24 , A = 12

  • 像 Case1 一样,我们又多了 4 个字节?

模式继续。 . . 感觉就像某种零填充来保持虚拟继承的派生类的大小为 8 的倍数,我不知道到底发生了什么以及为什么?

抱歉提前提出愚蠢的问题

【问题讨论】:

  • 您不应依赖可预测的班级规模。它们的存储是特定于实现的。任何“为什么”的问题都应该被认为是毫无意义的。
  • Data structure padding 是保持对象与处理器架构字长对齐的常见做法。
  • 当对象存储在数组中时,需要填充以保持 8 字节指针与 8 对齐。
  • 填充和对齐是一个实现细节,可能取决于也可能不取决于性能,也可能是硬件要求。应该有很多重复在谈论这些。
  • 你的感觉是对的。在您的平台上,指针似乎需要或更喜欢 8 字节对齐。如果不对齐(尽管会降低性能)或者不对齐(segv 崩溃),它们可能会很好。 C++ 倾向于更喜欢性能,即使它会在对象中造成一点填充。

标签: c++ vtable virtual-inheritance


【解决方案1】:

(Good Reads = this 为什么内存对齐很重要,this 为什么它对 CPU 很重要)。

  • 简而言之:为了执行性能关键算法,一些 CPU 需要对齐数据(否则会出现 segv 或一些异常错误),如果它没有对齐,那么它们必须执行几个额外的周期来获取正确的偏移量来访问数据从长远来看,这会给性能带来相当大的影响。

Case2:

填充到足以使offset 可被其对应的sizeof(data_member) 整除

struct B &amp; C 看起来像:
下一个偏移量设置为 16,大小为 = 16 个字节

struct D 看起来像:
下一个偏移量设置为 16,大小为 = 24 字节

  • 重要提示:存储顺序无关紧要,最终大小将相同,因为n = max(sizeof(data_members))final offset 应该能被n 整除,这里是n = 8。如果在Case2:struct B&amp;C 中,如果我先放入8(B|C::vptr) & offset = 8,然后4(int) & offset = 12final offset 将填充4 个字节以使他可以被n 整除,最后final offset = 24.

Case3: 中不需要填充,因为上面的 4 个填充字节是为新的整数成员解决的

Case4

struct D 看起来像:
下一个偏移量设置为 16,大小为 = 32 个字节

【讨论】:

  • 为什么没有出现答案表?它出现在我写答案和编辑过程中,但在最终答案中只有“|:-”符号存在??
猜你喜欢
  • 2014-04-30
  • 2018-11-12
  • 2019-10-11
  • 1970-01-01
  • 2017-04-20
  • 2013-06-21
  • 2023-03-22
  • 2016-08-16
  • 1970-01-01
相关资源
最近更新 更多