0

今天我读了<>。我遇到了一个问题。正如书中所说,

class Concrete1 {
public:
int val;
char bit1;
};

class Concrete2 : public Concrete1 {
public:
char bit2;
};

class Concrete3 : public Concrete2 {
public:
char bit3;
};

当我在mingw g++中运行代码时,三个类的空间是8、12、12。但是当我在vs2012中运行代码时,三个类的空间是8、12、16。当然,代码在vs2012是没有问题的。但是对于g++中的空间,我有一些问题,我尝试写一个示例代码,看看是否有问题。示例代码如下:

int main(void)
{
    Concrete2 con2;
    memset(&con2, 0, sizeof(con2));
    Concrete3  con3;
    con3.val = 3;
    con3.bit2 =  4;
    con3.bit3 = 5;
    Concrete2* con_ptr2 = &con2;
    Concrete2* con_ptr3 = &con3;
    *con_ptr3 = *con_ptr2;
    cout << con3.bit3<< endl;
    cout << sizeof(Concrete1) << endl;
    cout << sizeof(Concrete2) << endl;
    cout << sizeof(Concrete3) << endl;
    return 0;
}

而对于g++中的对象模型,代码没有问题。为什么在代码“*con_ptr3 = *con_ptr2;”之后,con3.bit3是5而不是0?谁能帮我 ?

4

1 回答 1

0

似乎结果是正确的,bit3 应该是 5,因为该赋值只影响 con3 的 Concrete1 和 Concrete2 部分。

赋值是按成员的,而不是按字节的。所以 "*com_ptr3 = *con_ptr2" 和 "memcpy(con_ptr3, con_ptr2, sizeof(Concrete2))" 不一样 默认的复制构造函数和默认的赋值操作符必须按成员和成员定义的顺序复制数据班上。这也意味着您不能指望具有任何特定值的填充字节。

大小差异只是因为 VS 和 gcc 处理填充略有不同。gcc 显然能够将 bit2 和 bit3 打包到同一个 32 位字中,而 VS 则不能。奇怪的是 gcc 也不能打包 bit1,导致大小为 8、8、8。

这可能是因为 gcc 认为 Concrete1 是 POD,但 Concrete 2 和 3 不是。与非 pod 相比,该标准对数据在 POD 类型中的布局方式有更严格的要求。编译器在非 pod 类型的类数据布局中具有更大的灵活性。

于 2013-10-10T02:18:56.830 回答