c ++中的对象大小是不可预测的

时间:2014-08-02 12:36:36

标签: c++ object memory size sizeof

#include<iostream>
using namespace std;
class Test
{
    int a;
    double d;
    char c;
};

int main()
{
    cout<<sizeof(int)<<endl;
    cout<<sizeof(double)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(Test)<<endl;
    Test sobj;
    Test *dobj = new Test();
    cout<<dobj<<endl;
    dobj++;
    cout<<dobj<<endl;
    cout<<sizeof(sobj)<<endl;
    cout<<sizeof(dobj)<<endl;

    return 0;
}

输出:

4
8
1
24
00380A08
00380A20
24
4

这里我的问题是当我们使用sizeof运算符打印类的大小时,它显示为24字节,因为没有应用填充它很清楚,但是当我看到地址之间的区别时它显示类大小为12字节,如何内存被分配.. ??

2 个答案:

答案 0 :(得分:3)

地址是十六进制的(如A所示)。 0x20是十进制的32:差异(十进制)不是20 - 8,它是32 - 8 = 24.

答案 1 :(得分:2)

首先,您的困惑来自以十六进制(基数为16)打印的地址。两个地址的不同部分是0x20(十进制为32)和0x08(十进制为8)。这两个数字之间的差异是0x18(十六进制),或十进制24。

其次,肯定会应用一些填充。基于各种类型大小的数字,在您的问题中,请考虑以下代码,它以三种不同的顺序定义结构的字段:

(实例http://coliru.stacked-crooked.com/a/eb6a1b3721b875f0

#include <iostream>

struct Layout1 {
    int a;
    double b;
    char c;
};

struct Layout2 {
    int a;
    char b;
    double c;
};

struct Layout3 {
    double a;
    int b;
    char c;
};

int main() {
    std::cout << sizeof(Layout1) << "\n";
    std::cout << sizeof(Layout2) << "\n";
    std::cout << sizeof(Layout3) << "\n";
    return 0;
}

请记住,在此示例中,double是8个字节,int是4个字节,char是1个字节。每个结构的布局如下,其中i表示int的一个字节,c表示char,d表示double的一个字节。符号-表示填充的一个字节。

                    1 1 1 1 1 1 1 1 1 1 2 2 2 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
i i i i - - - - d d d d d d d d c - - - - - - -  // layout 1
i i i i c - - - d d d d d d d d                  // layout 2
d d d d d d d d i i i i c - - -                  // layout 3

在第一个布局中,double成员必须在8字节边界上对齐,因此在int成员之后得到4个字节的填充。整个结构必须具有与其成员的最严格对齐相同的对齐方式,即双重结构。因此,char成员后面有7个字节的填充。

在第二种布局中,double必须仍然在8字节边界上,但char不需要;它可以在int之后立即打包,在double之前只留下三个字节的填充。由于结构以double结尾,因此不需要结束填充。

在第三种布局中,double启动struct,int(具有4字节对齐)可以立即跟随它(因为8是4的倍数)。 char(单字节对齐)可以跟随int,但是整个struct需要在8字节边界上对齐,因此在char字段之后有3个字节的填充。

上面的程序将输出:

24
16
16