5

下面的程序输出总是1 1 1。在《深入了解c++对象模型》一书中,提到它会给出偏移量。目的也是找出对象布局。但是,我对输出感到困惑。使用 g++ 4.5.2

class Test
{
    public:
        float a;
        float b;
        float c;
};

int main()
{
    float Test::*ptr = &Test::a;
    float Test::*ptr1 = &Test::b;
    float Test::*ptr2 = &Test::c;
    cout<<ptr<<endl;
    cout<<ptr1<<endl;
    cout<<ptr2<<endl;

    return 0;
}

输出:

1
1
1

编辑(后续问题):在书中提到origin.y = 0可以转换为&origin + (Point3d::y-1)origin 是 Point3d 的对象,y 是 Point3d 类的成员变量。虽然当我编译它给了我编译错误。

4

2 回答 2

19

您不能打印指向成员的指针,但指向成员的指针可以隐式转换为bool,当然可以打印这些指针。空指针转换为false,所有其他指针都转换为true。默认情况下,std::cout打印false0trueas 1

于 2012-08-19T19:00:58.300 回答
5

您写道您想找到内存偏移量。虽然 FredOverflow 所写的完全正确,但Test如果您想知道 和 的地址,a您应该创建一个类的实例。例如:bc

Test t;
float *ptr = &t.a;
float *ptr1 = &t.b;
float *ptr2 = &t.c;

在我的机器上,这会产生以下三个地址:

0x7fff564f8918
0x7fff564f891c
0x7fff564f8920

您会注意到它们sizeof(float)相隔 4 个字节(或 ),并且 a 的大小Test为 12 个字节(使用sizeof(Test))。此外, 的地址与 的&t地址0x7fff564f8918相同&t.a。这就是类实例的内存布局是如何Test形成的。

您还可以POD使用 查找类型成员的偏移量offsetof()

cout << offsetof(Test, a) << endl;
cout << offsetof(Test, b) << endl;
cout << offsetof(Test, c) << endl;

产量

0
4
8

注意offsetof(Test, b)本质上是一样的

(unsigned long long) &(((Test*) 0)->b) - (unsigned long long) (Test*) 0

回答您的后续问题:

由于与前面提到的相同的错误,该代码将不起作用。但是,如果您想计算y成员的地址origin并为其分配值0,则可以这样做:

class Point3d {
public:
  float x, y, z;
};

Point3d origin;
origin.y = 10;

// We take the address of origin, which points to the first member, 
// then add the offset to the member y.
float *ptr = (float*) ((unsigned long long) &origin + offsetof(Point3d, y));
cout <<  "Old value: " << *ptr << endl;
*ptr = 0;
cout <<  "New value: " << *ptr << endl;

产生输出:

Old value: 10
New value: 0

再次记住,这只是可能的,因为Point3d它是一种POD类型。

于 2012-08-19T19:22:41.923 回答