指向成员变量的指针

Pointer to member variable

本文关键字:指针 变量 成员      更新时间:2023-10-16

以下程序输出始终为 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)其中原点是 Point3d 的对象,y 是类 Point3d 的成员变量。虽然当我编译它给了我编译错误。

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

你写道,你想找到内存偏移量。虽然 FredOverflow 写的是完全正确的,但如果你想知道 abc 的地址,你应该Test你的类做一个实例。例如:

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

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

0x7fff564f8918
0x7fff564f891c
0x7fff564f8920

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

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

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

回答您的后续问题:

由于前面提到的相同错误,该代码将不起作用。但是,如果要计算origin y成员的地址并为其分配值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类型。