C ++对象,成员的内存位置偏移

时间:2009-11-05 02:13:34

标签: c++ memory object position member

是否有更好的方法来建立对象数据成员的位置偏移量而不是以下内容?

class object
{
  int a;
  char b;
  int c;
};

object * o = new object();
int offset = (unsigned char *)&(object->c) - (unsigned char *)o;
delete o;

4 个答案:

答案 0 :(得分:3)

在这种情况下,您的课程是POD,因此您可以使用offsetof中的<cstddef>宏。

实际上,在大多数实现中,对于大多数类,您可以使用与通常使用的offset相同的技巧:

int offset = &(((object *)0)->c) - (object *)0;

不需要实际创建一个对象,尽管你可能不得不抵制一些编译器警告,因为这不能保证工作。

还要注意,如果您的类具有任何多重继承,那么(至少)除了一个基类(void*)(base*)some_object != (void*)(derived*)some_object之外的所有基础。因此,您必须小心应用偏移量。只要你计算并应用它相对于实际定义字段的类的指针(也就是说,不要试图计算派生类指针的基类字段的偏移量),你几乎肯定会精细。对于对象布局没有任何保证,但大多数实现都以明显的方式进行。

从技术上讲,对于任何非POD类,从基指针谈论字段的“偏移”是没有意义的。对于该类的所有对象,指针之间的差异不必相同。

答案 1 :(得分:2)

无需实际创建对象:

(size_t)&(((object*)0)->c)

也就是说,地址为零的对象中成员的地址是该成员到对象中的偏移量。

当然,您需要访问该成员,因此您需要将其设为struct或添加public:访问修饰符。

这就是offsetof的实现方式,至少对大多数编译器来说都是如此。

答案 2 :(得分:2)

而不是指针 您可以使用指向成员的指针。

class X;
typedef int X::*    PtrToMemberInt;  // Declare a pointer to member.

class X
{
    int a;
    char b;
    float c;

    public:
    static PtrToMemberInt   getAPtr()
    {
        return &X::a;
    }

    int d;
};

int main()
{
    // For private members you need to use a public method to get the address.
    PtrToMemberInt aPtr = X::getAPtr();

    // For public members you can take the address directly;
    PtrToMemberInt dPtr = &X::d;


    // Use the pointer like this:
    X   a;
    a.*aPtr = 5;
    a.*dPtr = 6;
}

答案 3 :(得分:0)

要添加到Martins的答案,如Stroustrup的“设计和演变C ++”(第[13.11]节)所述:

  

指向数据成员的指针已经证明了这一点   表达布局的有用方式   实现中的C ++类   [Hübel,1992]

Sandeep非常善于转换原始论文并在http://sandeep.files.wordpress.com/2008/07/ps.pdf上提供

请注意,所描述的实现早于C ++ RTTI,但我偶尔也会使用指针到成员的东西。