C++类的大小和字节对齐

之前牛客网做C++测试题遇到结构体对齐和类大小的问题,没怎么在意,以为就记住了。可是今天看面试问题的时候又看到了,有的地方就想不起来了,所以决定开篇文章记录一下。

类大小的问题

1.空类

class A
{
};
sizeof(A); //1

解析:类的实例化就是为每个实例在内存中分配一块地址;每个类在内存中都有唯一的标识,因此空类被实例化时,编译器会隐含地为其添加一个字节,以作区分。

2.虚函数类

class A
{
    virtual void Fun();
};
sizeof(A); //4

解析:当一个类中包含虚函数时,会有一个指向其虚函数表的指针vptr,系统为类指针分配大小为4个字节(即使有多个虚函数)。

3.普通数据成员

class A
{
    int a;
    char b;
};

sizeof(A); //8

解析:普通数据成员,按照其数据类型分配大小,由于字节对齐(4),所以a+b=8字节。

4.静态数据成员

class A
{
    int a;
    static int b;
};

sizeof(A); //4

解析:**静态数据成员存放的是全局数据段,即使它是类的一个成员,但不影响类的大小;**不管类产生多少实例或者派生多少子类,静态成员数据在类中永远只有一个实体存在。而类的非静态数据成员只有被实例化时,才存在,但类的静态数据成员一旦被声明,无论类是否被实例化,它都已存在,类的静态数据成员可以说是一种特殊的全局变量。

5.普通成员函数

class A
{
    void Fun();
};

sizeof(A); //1

解析:类的大小与它的构造函数、析构函数以及其他成员函数无关,只与它的数据成员相关。

6.普通继承

class A
{
    int a;
};

class B:public A
{
    int b;
};

sizeof(B); //8

解析:普通类的继承,类的大小为本身数据成员大小+基类数据成员大小。

7.虚函数继承

virtual class A
{
    int a;
};

class B:virtual public A
{
    int b;
};

sizeof(B); //12

解析:虚函数类的继承,派生类大小=派生类自身成员大小+基类数据成员大小+虚拟指针大小(即使继承多个虚基类,也只有一个指向其虚函数表的指针vptr,大小为4字节)。

字节对齐

通过#pragma pack(4)实现,没到4的会补到4 比如char 是1 但szieof会输出4

#pragma pack的基本用法为:#pragma pack( n ),n为字节对齐数,其取值为1、2、4、8、16,默认是8

也能使用#pragma pack(push,1)来使字节以1个来对齐 , 使用#pragma pack(pop)来还原默认

字节对其对齐的作用和原因:
各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。

C++11新加关键字alignas(n)
__ attribute __((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐

参考文献:
https://www.cnblogs.com/sz-leez/p/7119232.html
https://www.jb51.net/article/84553.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值