关于C++中指向数据成员的指针的一些混淆

Some confusions about pointers to data-member in C++

本文关键字:指针 数据成员 C++ 关于      更新时间:2023-10-16
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。谁能解释一下这里发生了什么?

首先,指向成员的指针不需要实现为"对象的起始地址"(一个不是语言标准一部分的概念(的偏移量。事实上,某些类型的成员指针无法像那样实现。

相反,你所看到的只是basic_ostream::operator<<(bool) .指向成员的指针不能隐式转换为许多其他类型的,但可以转换为bool。您看到的1只是指示您已传递非 null 成员指针。

尽管 Sneftel 提供的答案是正确的,但这是查看指向成员的指针的"实际"(内部(值的一种方法:

#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.

大多数编译器都支持使用 <cstddef> 中定义的offsetof宏。只是要注意陷阱,引用cpp偏好:

如果类型不是标准布局类型,则行为未定义 (直到 C++17(有条件地支持使用 offset 宏 (自C++17年起(。

如果成员是静态成员或成员函数,则行为为 定义。

例:

#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;
}