Can 'this' pointer be different than the object's pointer?

后端 未结 5 1122
臣服心动
臣服心动 2021-02-05 11:28

I\'ve recently came across this strange function in some class:

void* getThis() {return this;}

And later in the code it is sometimes used like

相关标签:
5条回答
  • 2021-02-05 11:36

    I ran across something like this many (many many) years ago. If I recall correctly, it was needed when a class is manipulating other instances of the same class. One example might be a container class that can contain its own type/(class?).

    0 讨论(0)
  • 2021-02-05 11:38

    That might be a way to override the this keyword. Lets say that you have a memory pool, full initialized at the start of your program, for instance you know that at any time you can deal with a max of 50 messages, CMessage. You create a pool at the size of 50 * sizeof(CMessage) (what ever this class might be), and CMessage implements the getThis function.

    That way instead of overriding the new keyword you just override the "this", accessing the pool. It can also mean that the object might be defined on different memory spaces, lets say on a SRAM, in boot mode, and then on a SDRAM.

    It might be that the same instance will return different values for getThis through the program in such a situation, on purpose of course, when overriden.

    0 讨论(0)
  • 2021-02-05 11:41

    Of course, the pointer values can be different! Below an example which demonstrates the issue (you may need to use derived1 on your system instead of derived2 to get a difference). The point is that the this pointer typically gets adjusted when virtual, multiple inheritance is involved. This may be a rare case but it happens.

    One potential use case of this idiom is to be able to restore objects of a known type after storing them as void const* (or void*; the const correctness doesn't matter here): if you have a complex inheritance hierarchy, you can't just cast any odd pointer to a void* and hope to be able to restore it to its original type! That is, to easily obtain, e.g., a pointer to base (from the example below) and convert it to void*, you'd call p->getThis() which is a lot easier to static_cast<base*>(p) and get a void* which can be safely cast to a base* using a static_cast<base*>(v): you can reverse the implicit conversion but only if you cast back to the exact type where the original pointer came from. That is, static_cast<base*>(static_cast<void*>(d)) where d is a pointer to an object of a type derived from base is illegal but static_cast<base*>(d->getThis()) is legal.

    Now, why is the address changing in the first place? In the example base is a virtual base class of two derived classes but there could be more. All subobjects whose class virtually inherits from base will share one common base subject in object of a further derived class (concrete in the example below). The location of this base subobject may be different relative to the respective derived subobject depending on how the different classes are ordered. As a result, the pointer to the base object is generally different from the pointers to the subobjects of classes virtually inheriting from base. The relevant offset will be computed at compile-time, when possible, or come from something like a vtable at run-time. The offsets are adjusted when converting pointers along the inheritance hierarchy.

    #include <iostream>
    
    struct base
    {
        void const* getThis() const { return this; }
    };
    
    struct derived1
        : virtual base
    {
        int a;
    };
    
    struct derived2
        : virtual base
    {
        int b;
    };
    
    struct concrete
        : derived1
        , derived2
    {
    };
    
    int main()
    {
        concrete c;
        derived2* d2 = &c;
        void const* dptr = d2;
        void const* gptr = d2->getThis();
        std::cout << "dptr=" << dptr << " gptr=" << gptr << '\n';
    }
    
    0 讨论(0)
  • 2021-02-05 11:53

    Your class can have custom operator& (so &a may not return this of a). That's why std::addressof exists.

    0 讨论(0)
  • 2021-02-05 11:54

    No. Yes, in limited circumstances.

    This looks like it is something inspired by Smalltalk, in which all objects have a yourself method. There are probably some situations in which this makes code cleaner. As the comments note, this looks like an odd way to even implement this idiom in c++.

    In your specific case, I'd grep for actual usages of the method to see how it is used.

    0 讨论(0)
提交回复
热议问题