从成员指针获取指向封闭实例的指针
Get pointer to enclosing instance from member pointer
我有一个带有一些数据成员的自定义 class。我有一个指向 class' 数据成员之一的指针,我想要一个指向它的封闭实例的指针。例如:
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?
class不是POD类型,所以offsetof宏并不总是work/it给出编译警告。
是否可以获得指向 MyClass 实例的指针?
不,这在标准 C++ 中是不可能的。 offsetof
是唯一可移植的方式来做这样的事情,它只适用于标准布局 类。如果它不起作用(或者您无法抑制和忽略警告),那您就倒霉了。
您不能使用定义明确的 C++ 执行此操作,因为在不相关的类型之间进行转换是未定义的行为。
实际上,您可能会假设 class 的第一个成员的地址与 class 偏移指针大小的地址相同在你的系统上。 (这个指针是你的 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
实例。
CONTAINING_RECORD
是可能适合您的宏,它经常与链表一起使用,其中指向下一个和上一个项目的指针嵌入到另一个结构中。
我有一个带有一些数据成员的自定义 class。我有一个指向 class' 数据成员之一的指针,我想要一个指向它的封闭实例的指针。例如:
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?
class不是POD类型,所以offsetof宏并不总是work/it给出编译警告。
是否可以获得指向 MyClass 实例的指针?
不,这在标准 C++ 中是不可能的。 offsetof
是唯一可移植的方式来做这样的事情,它只适用于标准布局 类。如果它不起作用(或者您无法抑制和忽略警告),那您就倒霉了。
您不能使用定义明确的 C++ 执行此操作,因为在不相关的类型之间进行转换是未定义的行为。
实际上,您可能会假设 class 的第一个成员的地址与 class 偏移指针大小的地址相同在你的系统上。 (这个指针是你的 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
实例。
CONTAINING_RECORD
是可能适合您的宏,它经常与链表一起使用,其中指向下一个和上一个项目的指针嵌入到另一个结构中。