c++字节对齐

为什么C++ 中空类的大小是1个字节?

C++中的数据对齐

不同数据类型所占的内存大小

  32 位 64 位
char 1 1
int 4 4
short 2 2
long 4 8
float 4 4
double 8 8
指针 4 8

共用体的大小


union A{
    int a[5];
    char b;
    double c;
};
cout << sizeof(A) << endl;

上面求出共用体的大小为:24

union 中变量共用内存,应以最长的为准,A 中最长的成员是数组 a,其长度为 20。与结果不一样,这是因为在共用体内变量的默认对齐方式,必须以最长的 double(8Byte)对齐,所以得到 sizeof(A) = 24。所以将共用体内的 int a[5] 修改成 int a[6] 后,结果仍然不变;但如果将 int a[5] 修改成 int a[7],结果就变成 32。

对齐系数:每个平台上的编译器都有默认对齐系数 n,但是可以通过 #pragma pack(n) 来设定。 有效对齐系数:对于一个复杂类型变量,有效对齐系数 = min(对齐系数 n,复杂类型中最长数据类型的长度)。比如设定的对齐系数为 8,而结构体中最长的是 int,4个字节,那么有效对齐值为 4。

通过下面的例子说明有效对齐系数:


#pragma pack(4)

union A{
    int a[5];
    char b;
    double c;
};

cout << sizeof(A) << endl;

输出为:20

这是因为通过 

#pragma pack(n)
 设置对齐系数为 4,所以实际的有效对齐系数为:min(4, sizeof(double)) = 4,所以最后共用体 A 的大小为 5*int(4) = 20。

类对象的大小
关于类占用的内存空间,有以下几点需要注意:

如果类中含有虚函数,则编译器需要为类构建虚函数表,类中需要存储一个指针指向这个虚函数表的首地址,注意不管有几个虚函数,都只建立一张表,所有的虚函数地址都存在这张表里,类中只需要一个指针指向虚函数表首地址即可。

类中的静态成员是被类所有实例所共享的,它不计入sizeof计算的空间。

类中的普通函数或静态普通函数都存储在栈中,不计入sizeof计算的空间。

类成员采用字节对齐的方式分配空间。

例子:


class B{
    public:
        virtual void funa();
        virtual void funb();
        void func();
        static void fund();
        static int si;

    private:
        char c;
        int i;
};

以上类的大小:sizeof(B) = 12(32位);sizeof(B) = 16(64位)。

根据以上的规则,多个虚函数只建立一张虚函数表,类中只存有一个指向虚函数表首地址的指针;普通函数 func() 不计入;静态成员 fund() 与 si 也不计入;char c 占用 1Byte,再需补充 3Byte;int i 占用 4Byte。所以总的大小为:一个指针大小+1+3+4。32位系统指针大小为 4Byte,所以为 12Byte;64位系统指针大小为 8Byte,所以总大小为 16Byte。

C/C++中 sizeof 的用法总结

c++ 要掌握的知识

 
喜欢 0
分享