class Foo {
public:
int a = 1;
int b = 2;
};
int main() {
Foo foo;
cout << &Foo::a << endl;//output 1
cout << &Foo::b << endl;//also output 1
}
我们知道指向成员数据的指针应指出与对象起始地址的相对偏移量,但正如示例所示,指向Foo :: a和Foo :: b的指针都得到1
。有人能解释这里发生了什么吗?
答案 0 :(得分:6)
首先,指向成员的指针不需要实现为对象&#34;起始地址的偏移量。 (不属于语言标准的概念)。事实上,某些类型的成员指针无法像这样实现。
相反,您所看到的只是basic_ostream::operator<<(bool)
。成员的指针不能隐式转换为许多其他类型,但它们可以转换为bool
。您查看的1
只是表明您已经传递了非空成员指针。
答案 1 :(得分:4)
虽然Sneftel提供的answer是正确的,但这是查看指向成员的指针的“实际”(内部)值的一种方法:
#include <iostream>
struct x {
int a, b;
};
int main() {
int x::* pa = &x::a;
int x::* pb = &x::b;
std::cout << pa << ' ' << pb << '\n';
std::cout << *(int*)&pa << ' ' << *(int*)&pb << '\n';
}
这可能有不同的值或导致未定义的行为,取决于实现。此外,我们无法保证sizeof int == sizeof pa
。
答案 2 :(得分:4)
大多数编译器都支持使用offsetof
中定义的<cstddef>
宏。请注意陷阱,引用cppreference:
如果type不是标准布局类型,则行为未定义 (直到C ++ 17)有条件地支持使用offsetof宏 (自C ++ 17起)。
如果member是静态成员或成员函数,则行为是 未定义。
示例:
#include <iostream>
#include <cstddef>
class Foo {
public:
int a;
int b;
};
int main() {
std::cout << offsetof(Foo, a) << std::endl;
std::cout << offsetof(Foo, b) << std::endl;
}