【问题标题】:What causes difference of size of structs between inheritance and member? [duplicate]是什么导致继承和成员之间结构大小的差异? [复制]
【发布时间】:2021-03-11 17:11:17
【问题描述】:

我无法理解以下代码中 C 和 C2 大小不同的原因:

#include <iostream>

struct A {
    int* x;
};

struct B {
    A a;
    int y;
};

struct C : B {
   int z;
};

struct B2 : A {
   int y;
};

struct C2 : B2 {
   int z;
};
    
int main()
{
    std::cout << sizeof(A) << std::endl; // 8
    std::cout << sizeof(B) << std::endl; // 16
    std::cout << sizeof(C) << std::endl; // 24
    std::cout << sizeof(B2) << std::endl; // 16
    std::cout << sizeof(C2) << std::endl; // 16
}

https://wandbox.org/permlink/GEWj2LQxloC34lNS

我(可能)理解的是,

  • C 具有以下内存布局
|0      |4      |8      |12     |16      |20     |
|A::x-----------|B::y---|padding|C::z----|padding|
  • C2 具有以下内存布局。
|0      |4      |8      |12      |
|A::x-----------|B::y---|C::z----|

在C中,似乎结构B的填充仍然存在,但在C2中,结构B2的填充似乎被压缩了。造成这种差异的原因是什么? (是在C++标准中定义的吗?是什么规则?)

【问题讨论】:

  • 添加多少填充是实现定义的。
  • "造成这种差异的原因是什么?"你到底是什么意思? CC2 的大小不同?你问为什么sizeof(C)=24sizeof(C2) == 16
  • @Hammer User.... 这个问题没有多重继承,那是错误的重复。
  • @largest_prime_is_463035818 我想知道的是为什么B的填充保留在C中,而B2的填充没有保留在C2中。
  • this question and accepted answer 更详细地介绍(可能被视为重复)

标签: c++ sizeof


【解决方案1】:

C++ 允许在派生类中引入的子对象与基础子对象重叠(填充),只要这些对象不是标准布局即可。它不允许成员子对象之间的任何重叠,或标准布局基础子对象的重叠。

查看struct B 的大小和布局,了解为什么struct C 有内部填充。

【讨论】:

  • 我认为这并不能真正回答问题。为什么C::z 不能与基础对象B 中的填充重叠,而C2::z 可以 与基础对象B2 中的填充重叠?还是我没有完全理解“它不允许成员子对象之间有任何重叠”是什么意思?
  • @Kevin:你说得对,我回答了struct C { B base; int z; }; 现在展开了。
  • 我想我现在明白了。 struct B 是标准布局,但 struct B2 不是 - 根据cppreference,标准布局的要求之一是“具有在同一类中声明的所有非静态数据成员和位字段(全部在在某个基础上派生或全部)"
  • 是的,这就是本质的区别。标准布局子对象必须与外部代码兼容...例如,如果您将 struct C 传递给接受具有输出参数语义的 B* 的函数,并且该函数使用 memcpy 写入它,它将被丢弃内部填充,如果其他一些对象与内部填充重叠,这会毁了你的一天。当B 是标准布局时,C++ 会确保这一点。
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 2010-11-04
  • 2011-03-22
  • 2011-01-19
  • 2012-11-06
  • 2011-08-01
  • 1970-01-01
相关资源
最近更新 更多