对象模型的问题疑惑? sizeof的问题?

时间:2022-06-01 23:29:53
#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?

13 个解决方案

#1


引用 楼主 chp845 的回复:
#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

#2


对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table

#3


恩,这要看自身编译器的实现!!好像论坛蛮多这样子的讨论贴

#4


引用 2 楼 derekrose 的回复:
对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table


诶 是空的class啊 楼主可以debug看一看A里面到底有什么 我也忘了。。。

#5


引用 2 楼 derekrose 的回复:
对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table

不知道的话,我能够知道标准上:应该是9吗?

#6


引用 1 楼 lyyslsw 的回复:
Quote: 引用 楼主 chp845 的回复:

#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!

#7


研究包含虚基类的对象的大小 没有太大意义,因为不同编译器的实现差异太大。

#8


lz这个明显是inside the c++ object model上面的例子,
书上说的很明确了  视编译器而定

#9


参考一下

c:\demo>type demo.cpp
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};

int main()
{
      printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
      return 0;
}


c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar    size(8):
        +---
        | +--- (base class Y)
 0      | | {vbptr}
        | +---
        | +--- (base class Z)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base X)
        +---

FooBar::$vbtable@Y@:
 0      | 0
 1      | 8 (FooBard(Y+0)X)

FooBar::$vbtable@Z@:
 0      | 0
 1      | 4 (FooBard(Z+0)X)


vbi:       class  offset o.vbptr  o.vbte fVtorDisp
               X       8       0       4 0



c:\demo>demo
Y:4 Z:4 A:8

c:\demo>

#10


引用 9 楼 mujiok2003 的回复:
参考一下

c:\demo>type demo.cpp
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};

int main()
{
      printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
      return 0;
}


c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar    size(8):
        +---
        | +--- (base class Y)
 0      | | {vbptr}
        | +---
        | +--- (base class Z)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base X)
        +---

FooBar::$vbtable@Y@:
 0      | 0
 1      | 8 (FooBard(Y+0)X)

FooBar::$vbtable@Z@:
 0      | 0
 1      | 4 (FooBard(Z+0)X)


vbi:       class  offset o.vbptr  o.vbte fVtorDisp
               X       8       0       4 0



c:\demo>demo
Y:4 Z:4 A:8

c:\demo>

vc 2010

#11


引用 6 楼 chp845 的回复:
Quote: 引用 1 楼 lyyslsw 的回复:

Quote: 引用 楼主 chp845 的回复:

#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!

标准从来没规定应该是多少。
你说的“g++对象模型”根本不是标准的内容,标准本身不是哪个具体的编译器厂商定的。
标准里有个关于大小的规定倒是,就是sizeof(X)不能为零,但是被另一个STD-LY类型(之前叫POD类型)继承S的时候,sizeof(S)可以只考虑S自身的成员占用情况(而让X在其中不占任何实际空间)
但是lz的例子里,Y、Z虚继承于X,结果Y、Z、A都已经不是STD-LY类型了,所以sizeof具体应该为多少,标准已经没有相应的规定了,只要是固定大小就行,编译器设计者可以自己决定

#12


补充一下,虚继承、虚函数的实现方式目前有虚表、二叉树、hash表等方式,现在主流的编译器多使用虚表这种实现方式、讨论的也比较多,但不要认为是标准规定了用虚表实现。虚表不是标准里的内容、标准也没规定该用什么方式实现虚函数、虚继承这些。

#13


哎,楼主《深度探索C++对象模型》基本白看了,竟然把virtual继承无视了。

#1


引用 楼主 chp845 的回复:
#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

#2


对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table

#3


恩,这要看自身编译器的实现!!好像论坛蛮多这样子的讨论贴

#4


引用 2 楼 derekrose 的回复:
对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table


诶 是空的class啊 楼主可以debug看一看A里面到底有什么 我也忘了。。。

#5


引用 2 楼 derekrose 的回复:
对象模型的问题疑惑? sizeof的问题? 楼主知道不知道有个东西叫virtual table

不知道的话,我能够知道标准上:应该是9吗?

#6


引用 1 楼 lyyslsw 的回复:
Quote: 引用 楼主 chp845 的回复:

#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!

#7


研究包含虚基类的对象的大小 没有太大意义,因为不同编译器的实现差异太大。

#8


lz这个明显是inside the c++ object model上面的例子,
书上说的很明确了  视编译器而定

#9


参考一下

c:\demo>type demo.cpp
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};

int main()
{
      printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
      return 0;
}


c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar    size(8):
        +---
        | +--- (base class Y)
 0      | | {vbptr}
        | +---
        | +--- (base class Z)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base X)
        +---

FooBar::$vbtable@Y@:
 0      | 0
 1      | 8 (FooBard(Y+0)X)

FooBar::$vbtable@Z@:
 0      | 0
 1      | 4 (FooBard(Z+0)X)


vbi:       class  offset o.vbptr  o.vbte fVtorDisp
               X       8       0       4 0



c:\demo>demo
Y:4 Z:4 A:8

c:\demo>

#10


引用 9 楼 mujiok2003 的回复:
参考一下

c:\demo>type demo.cpp
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};

int main()
{
      printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
      return 0;
}


c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar    size(8):
        +---
        | +--- (base class Y)
 0      | | {vbptr}
        | +---
        | +--- (base class Z)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base X)
        +---

FooBar::$vbtable@Y@:
 0      | 0
 1      | 8 (FooBard(Y+0)X)

FooBar::$vbtable@Z@:
 0      | 0
 1      | 4 (FooBard(Z+0)X)


vbi:       class  offset o.vbptr  o.vbte fVtorDisp
               X       8       0       4 0



c:\demo>demo
Y:4 Z:4 A:8

c:\demo>

vc 2010

#11


引用 6 楼 chp845 的回复:
Quote: 引用 1 楼 lyyslsw 的回复:

Quote: 引用 楼主 chp845 的回复:

#include <iostream>
#include <stdio.h>

using namespace std;

class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
    printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
    return 0;
}

运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16 

请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?


这不是C++标准的东西吧, 这依赖于编译器自身

标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!

标准从来没规定应该是多少。
你说的“g++对象模型”根本不是标准的内容,标准本身不是哪个具体的编译器厂商定的。
标准里有个关于大小的规定倒是,就是sizeof(X)不能为零,但是被另一个STD-LY类型(之前叫POD类型)继承S的时候,sizeof(S)可以只考虑S自身的成员占用情况(而让X在其中不占任何实际空间)
但是lz的例子里,Y、Z虚继承于X,结果Y、Z、A都已经不是STD-LY类型了,所以sizeof具体应该为多少,标准已经没有相应的规定了,只要是固定大小就行,编译器设计者可以自己决定

#12


补充一下,虚继承、虚函数的实现方式目前有虚表、二叉树、hash表等方式,现在主流的编译器多使用虚表这种实现方式、讨论的也比较多,但不要认为是标准规定了用虚表实现。虚表不是标准里的内容、标准也没规定该用什么方式实现虚函数、虚继承这些。

#13


哎,楼主《深度探索C++对象模型》基本白看了,竟然把virtual继承无视了。