以下程序输出始终为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类的成员变量。虽然当我编译它时给了我编译错误。
答案 0 :(得分:17)
您无法打印指向成员的指针,但指向成员的指针可以隐式转换为bool
,当然也可以打印。空指针转换为false
,所有其他指针转换为true
。默认情况下,std::cout
将false
打印为0
,将true
打印为1
。
答案 1 :(得分:4)
您写道,您想要找到内存偏移量。虽然FredOverflow写的内容完全正确,但如果您想知道Test
,a
和b
的地址,则应该创建类c
的实例。例如:
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
的实例的内存布局。
您还可以使用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
类型。