C++类的实例化对象的大小之SIZEOF()

6 篇文章 0 订阅

之所以写这篇《C++类的实例化对象的大小之sizeof()》总结一下。你不知道的C++类的实例化对象的大小之sizeof()。个人是在vscode上运行的,发现sizeof *所占的内存8字节,int * 也是8字节,int 占4字节,虚函数所占据的内存也是8字节,这个要根据编辑器的不同自行进行调整。据估计是指针在64位的sizeof占据的大小的问题,需要自己把握,看准是怎么样的编译器,是多少位的

实例一:

class A
{
};

A a;

cout << sizeof(a) << endl;

执行结果:1

解释:空类,没有不论什么成员变量或函数。即没有不论什么存储内容;可是由A a可知,空类仍然可以实例化。一个类可以实例化,编译器就需给它分配内存空间,来指示类实例的地址。这里编译器默认分配了一个字节,以便标记可能初始化的类实例。同一时候使空类占用的空间最少(即1字节)。

实例二:

class B

{
private:
int a;
};

B b;
cout << sizeof(b) << endl;

执行结果:4

解释:当类中有其他成员占领空间时,那一个字节就不算在内了,如本题:结果是4,而不是1+4=5。

实例三:

class BB

{

private:

int a ;

char b;

};

BB bb;

cout << sizeof(bb) << endl;

执行结果:8

解释:什么?怎么会是8?不应该是4 + 1 = 5吗?这里考察了对齐,涉及到编译器的优化

对于大多数CPU来说,CPU字长的整数倍操作起来更快,因此对于这些成员加起来不够这个整数倍,有可能编译器会插入多余的内容凑足这个整数倍。此外,有时候相邻的成员之间也有可能由于这个目的被插入空白,这个叫做“补齐”(padding)。所以,C++标准紧紧规定成员的排列依照类定义的顺序,可是不要求在存储器中是紧密排列的。因此,如上的一个字节的char在存储时被补全了,成为了4个字节。

实例四:

class C

{

private:

int a ;

char *p;

};

C c;

cout << sizeof© << endl;

执行结果:16

解释:普通情况下,假设是指针,则不管指针指向的是什么数据类型,都占4个字节的存储空间。但是在vscode64占据的是8字节,要考虑是什么类型的编译器

实例五:

class D

{
public:
D()
{
}
virtual ~D()
{
}

private:
int a ;
char \*p;
};
D d;

cout << sizeof(d) << endl;

执行结果:24

解释:考察虚函数。当类含有虚函数时,(不论是自己的虚函数,还是继承来的),那么类中就有一个成员变量信息:虚函数指针(8个字节)。这个指针指向一个虚函数表,虚函数表的第一项是类的typeinfo信息,之后的项为此类的全部虚函数的地址。字节对齐

更进一步的解释:当类中有虚函数的时候,编译器会为类插入一个我们看不及爱你的数据并建立一个表。这个表就是虚函数表。那个我们看不见的数据就是指向虚函数表的指针——虚表指针。虚函数表就是为了保存类中的虚函数的地址。

我们能够把虚函数表理解成一个数组,数组中的每一个元素存放的就是类中虚函数的地址。当调用虚函数的时候,程序不是像普通函数那样直接跳到函数的代码处,而是先取出虚表指针即得到虚函数表的地址,依据这个来到虚函数表里,从这个表理取出该函数的指针。最后调用该函数。

实例六:

class E

{

public:

E()

{

}

virtual ~E()

{

}

private:

int a ;

char \*p;

static int b;

};

E e;

cout << sizeof(e) << endl;

执行结果:24

解释:考察静态成员变量的内存分配。

因为静态成员变量是在静态存储区分配空间的,它不属于实例的一部分。因此类中的static成员变量不占领空间

实例七:

class F:public E

{

public:

F()

{

}

~F()

{

}

private:

int c;

};

E e;

cout << sizeof(e) << endl;

执行结果:32

解释:派生类对象的存储空间 = 基类存储空间 + 派生类特有的非static数据成员的空间,也要遵循所继承的最大的那个自己长度。个人理解是的顺序是成员变量的,按照顺序char *在int c之前

实例八:

class G: public virtual E

{

public:

G()

{

}

~G()

{

}

private:

int c;

};

G g;

cout << sizeof(g) << endl;

执行结果:40

解释:假设是虚继承的话,类对象的存储空间大小 = 基类的存储空间 + 派生类特有的非static数据成员的存储空间 + 每个类的虚函数存储空间(这选函数的存储只算一次的)

实例九:

class H: public virtual E

{

public:

H()

{

}

~H()

{

}

virtual void GetValue()

{

}

private:

int c;

};

H h;

cout << sizeof(h) << endl;

执行结果:40

解释:对照实例八,依照上面的解释:类对象的存储空间大小 = 基类的存储空间 + 派生类特有的非static数据成员的存储空间 + 每个类的虚函数存储空间(sizeof(h) = 12(E基类的存储空间) + 4(G特有的非static数据成员的存储空间) + 4(E类的虚函数的存储空间,假设E类中有多个虚函数,仅仅算一次)+ 4(H类的虚函数的存储空间,假设H类中有多个虚函数。仅仅算一次))。

如上,就是我对于这样的类型的总结,这样的问题仅仅能出现一次!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值