Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从空类继承时如何解释此sizeof结果 假设我有以下的C++结构定义: struct Empty {}; struct Tmp : public Empty { int x; }; struct Tmp2 : public Empty { Tmp tmp;}; struct Tmp3 { Tmp tmp; };_C++_Inheritance_Struct - Fatal编程技术网

从空类继承时如何解释此sizeof结果 假设我有以下的C++结构定义: struct Empty {}; struct Tmp : public Empty { int x; }; struct Tmp2 : public Empty { Tmp tmp;}; struct Tmp3 { Tmp tmp; };

从空类继承时如何解释此sizeof结果 假设我有以下的C++结构定义: struct Empty {}; struct Tmp : public Empty { int x; }; struct Tmp2 : public Empty { Tmp tmp;}; struct Tmp3 { Tmp tmp; };,c++,inheritance,struct,C++,Inheritance,Struct,预计的sizeof(Tmp3)==sizeof(Tmp)==4。 然而,sizeof(Tmp2)==8,我想不出为什么。。。?你能帮我解释一下吗?谢谢 在Tmp的情况下,允许使用,并且您的编译器正在应用它 在Tmp2的情况下,EBCO被禁用,因为数据成员Tmp2::tmp也是一个空的。这是因为Tmp2有两个相同类型的子对象(基类子对象及其第一个数据成员)。它们必须有不同的地址*。否则,就不可能区分两者 这意味着基类会影响派生类的大小 < P> >从 1.8 C++对象模型< /强>除非对象是位

预计的
sizeof(Tmp3)==sizeof(Tmp)==4

然而,
sizeof(Tmp2)==8
,我想不出为什么。。。?你能帮我解释一下吗?谢谢

Tmp
的情况下,允许使用,并且您的编译器正在应用它

Tmp2
的情况下,EBCO被禁用,因为数据成员
Tmp2::tmp
也是一个
空的
。这是因为
Tmp2
有两个相同类型的子对象(基类子对象及其第一个数据成员)。它们必须有不同的地址*。否则,就不可能区分两者

这意味着基类会影响派生类的大小



< P> >从<强> 1.8 C++对象模型< /强>除非对象是位字段或大小为零的基类子对象,否则该对象的地址就是它所占用的第一个字节的地址。如果一个对象是另一个对象的子对象,或者如果至少一个对象是大小为零的基类子对象,并且它们的类型不同,则两个非位字段的对象可能具有相同的地址;否则,它们将有不同的地址。“

规则是,同一类型的两个不同的对象必须有不同的地址,这也是空对象仍然具有正大小的原因。因为这仅适用于同一类型的对象,所以两种不同类型可以共享存储,这是”空基类优化”

现在,您的
Tmp
包含(作为基类)一个
Empty
子对象。此外,
Tmp2
有两个这样的子对象,一个通过其基类,另一个作为普通成员。此外,它还有一个
int
。因此,您需要的空间不仅仅是
int
,即
sizeof(int)至少是+1。可能是由于填充,它的结尾是8个字节


BTW:考虑一个<代码> TMP4/COD>,它继承了<代码> TMP ,还包含了一个<代码> TMP 。一个可能与“代码> TMP2 < /代码>的大小相同。

< P> <强>这是一个可怕的非标准HACK <强>…但是如果由于某种原因,你想要<代码> siZeof(TMP2)。==4
,有一种方法可以在我测试过的所有编译器中使用

struct EvilEmpty
{
    char evil[0];
};
通过提供一个非法(但被广泛接受为扩展)的零大小数组作为成员,它不再被视为空数组,编译器被欺骗,没有意识到它可能会非法地将两个具有相同类的不同对象放在同一地址。(注意,这比合法的空类小。)



显然,这是所有导致C和C++标准都禁止第一个零大小对象的问题。

你使用什么编译器?用MSVC,我为所有的人都得到4,而对于sisiof(1),我得到了所有的。,@BarmakShemirani MSVC不是一个很好的编译器,如果你想要任何与标准一致性稍有相似的东西,就可以使用它进行测试。4的大小实际上可以符合标准,这取决于两个
Empty
子对象的地址是否相同或不同。
tmp2t;cout@o11c的输出是什么,MSVC到底违反了什么这个案子?@UlrichEckhardt我刚试过,他们的地址是一样的。这不能回答问题吗?@MattMcNabb不是这个问题的措辞,但可能是这个问题的初衷。如果不是OP,可能是其他人在搜索这个问题。@MattMcNabb:这仍然有助于帖子。我通常会开始这样的回答(我过去也有过这样的例子)“不是对你的问题的直接回答,而是……”规则是同一类型的两个不同对象必须有不同的地址“你能证明这一说法吗?就所讨论的版面而言,当然我不能从C++中提取适当的诗句和C++标准,这证明了这一点,我需要为此做些研究。但是,你在“布局问题”的上下文中要求证明(<代码> TMP2<代码>?)这是一个问题,我不理解,因为除了C++的标准之外,一般规则是不能证明的,而且它又独立于这里的布局。据我所知,布局的布局违反了标准布局的规则。因此,它使它成为非标准的,因此非POD。但是我在标准WHI中看不到任何东西。ch将禁止这种布局
Tmp2
布局不是标准布局,因为
9/7
没有与第一个非静态数据成员相同类型的基类
)@ixSci-同一类型的两个不同对象必须具有不同的地址,否则您无法将它们区分开来。不同类型的对象,如结构及其第一个成员,可以具有相同的地址。为什么它们必须具有不同的地址?@ixSci这是标准中指定的。我添加了一个带有引号的脚注。我很难破译它s短语,你能帮我一点忙吗?“如果一个对象是另一个的子对象,那么两个不是位字段的对象可能具有相同的地址”-好的,
tmp
Tmp2
的子对象,或者如果至少有一个是大小为零的基类子对象,并且它们的类型不同”-
Empty
Tmp2
Tmp
的基类子对象,而
Empty
是不同的类型。为什么它们不能有相同的地址?@ixSci示例是嵌套有点复杂,但是
Tmp
Empty
,所以它的第一个子对象是
Empty
对象。该子对象具有e与
Tmp2
Tmp
子对象的地址相同,并且必须与
Tmp2
@ixSci的基子对象的地址不同:重要的是,相同类型的不同对象始终具有不同的地址,并且两个对象彼此不相关(父对象)对象也总是有不同的地址