简体   繁体   中英

Can I get reference of an object with address of member variable in C++?

Is it possible to get a reference to an object if I have only the address of a member variable of that object?

class example{
    public:
        int var;
};


int main(){
    
    example exampleObject;
    
    int* point=&exampleObject.var;
    
    example* objPointer; // can i get objPointer to point to exampleObject only using point
    return 1;
}

Can I get reference of an object with address of variable in C++?

Based on the example code, there appears to be a crucial word missing from this qustion. It appears that you want to get reference to an object with an address of a member variable of that object, rather than a variable of the class type.

Potentially yes, but there are limitations.

Only if the class in question is a standard layout class is this possible. In that case, you can reinterpret a pointer to the first member as a pointer to the class itself. You can then indirect through the pointer to get a reference:

static_assert(std::is_standard_layout_v<example>);
example* objPointer = reinterpret_cast<example*>(point);
assert(objPointer == &exampleObject); // guaranteed to pass

Getting pointer to a standard layout class based on a member other than the first may be possible using the offsetof macro, although all attempts to implement that idea that I've seen rely on something that is either technically undefined behaviour, or at least implementation defined.

Here is the implementation from the Linux kernel (not written in C++, but C, which may be more relaxed in what is allowed):

 #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })

typeof is not in standard C++, nor even in standard C, but is a GNU language extension. This also uses a statement expression (not to be confused with expression statements), which is another GNU extension.

Alert : don't do it regularly since it's very easy to mess thing out

#include <iostream>

class example{
public:
    int var;
};


int main(){

    example exampleObject{15};

    int* point=&exampleObject.var;

    example* objPointer = reinterpret_cast<example*>(point);
    std::cout << objPointer->var;
    return 0;
}

now objPointer will points to the original object, however this works only because of how object are managed, and so because since var is the first property of a class without a base class, its address will be the same of the object, but if you have something like this:

class example{
public:
    int var;
    int var2;
};


int main(){

    example exampleObject{15, 16};

    int* point=&exampleObject.var2;

    example* objPointer = reinterpret_cast<example*>(point);
    std::cout << objPointer->var2;
    return 1;
}

It won't work, because var2 is not saved in the same address where the object is saved, since there is var saved before it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM