【问题标题】:Get pointer to enclosing instance from member pointer从成员指针获取指向封闭实例的指针
【发布时间】:2023-04-04 09:23:01
【问题描述】:

我有一个包含一些数据成员的自定义类。我有一个指向类的数据成员之一的指针,我想有一个指向其封闭实例的指针。例如:

class MyClass{
public:
    int a;
    int b;
    virtual ~MyClass(){//because MyClass is not POD type
    }
};

...

int* aptr = ...; //something valid, and i know its a pointer to a MyClass::a member
MyClass* classptr = ?; //how can i get a pointer to the class instance?

该类不是 POD 类型,因此 offsetof 宏并不总是有效/它会给出编译警告。

是否可以获得指向 MyClass 实例的指针?

【问题讨论】:

  • 我不认为这是可能的,成为MyClass 非 POD。

标签: c++ pointers member-pointers


【解决方案1】:

不,这在标准 C++ 中是不可能的。 offsetof 是做这种事情的唯一可移植方式,它只适用于标准布局类。如果它不起作用(或者您无法抑制并忽略警告),那么您就不走运了。

【讨论】:

    【解决方案2】:

    你不能使用定义明确的 C++ 来做到这一点,因为不相关类型之间的转换是未定义的行为。

    实际上,您可能会假设一个类的第一个成员的地址与该类的地址相同,该地址是系统上指针大小的偏移量。 (这个指针是 v-table 的实现,并且在 C++ 实现中相当一致。)然后,如果您对数据成员的打包做出一些假设,那么您可以手动调整指针以从一个数据成员移动到其他。 offsetof 是另一种技术,可以在这里为您提供帮助,但在您的上下文中仍未明确定义。

    要么用特定的编译器断言乱扔你的源代码(因为你正在限制可移植性),要么采用不同的技术。我当然会采用后者。

    这里有一些 非常 糟糕的代码,向您展示了如何做到这一点。考虑

    struct Foo
    {
        virtual ~Foo(){}; /*introduce a v-table*/
        int n;
    };
    

    还有,

      Foo foo;
      foo.n = 0xdeadbeef; // To test
      int* p = &foo.n; // Suppose this is our pointer.
      char* pp = (char*)(void*)p; // This cast is undefined behaviour.
      pp -= 8; // Skip over 64 bit v-table. More undefined behaviour.
      Foo* ph = (Foo*)(pp); // Yet more undefined behaviour.
    

    ph 指向一个Foo 实例。

    【讨论】:

    • offsetof宏中的成员指针不是跳过v表吗?如果是这样,那为什么它不适用于非 POD 类型?
    • 我的理解是offsetof不是为多态类型定义的
    • 确实不是 (en.cppreference.com/w/cpp/types/offsetof),但是通过使指针指向第一个数据成员,它不会跳过前面的 v-table 吗?指针操作哪里出错了?
    • 我不知道。一旦您跳过了 v-table,它可能会起作用。但请记住,它不会被明确定义。我不建议在 任何 情况下将 offsetof 用于多态类型。
    【解决方案3】:

    CONTAINING_RECORD 是可能对您有用的宏,它经常与链表一起使用,其中指向下一项和上一项的指针嵌入在另一个结构中。

    【讨论】:

    • 您可能应该提到它是特定于 MSVC 的。
    • 我也在尝试将它与链接列表一起使用,并且可以使用这个宏,但是我正在尝试创建可移植代码,而不仅仅是 Windows 特定的。
    • 我几乎不会称之为 MSVC 特定的。 MSVC 可能与定义它的 sdk 捆绑在一起,但例如 Reactos 也定义了它。 (使用 gcc 和 MSVC 构建得很好
    • 在 linux 领域这通常称为container_of
    猜你喜欢
    • 2016-02-25
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多