Changing what THIS is

2019-07-20 12:49发布

问题:

Is there a way to change what THIS point to?

class foo{...}

foo* fooinstance = new foo();
foo* otherfooinstance = new foo();

void
foo::bar(){
    this = otherfooinstance;
}

fooinstance->bar();

for those of you who are wondering in what case I would change the this pointer here is case. I had to do a tree recursion where I had to remove intermediate nodes.. for this example lets assume the intermediate nodes of removal have the title d. and these intermediate nodes only have one child. So in lisp notation if we have a tree like

(g (d (i 4)) (i 5))

the function removeIntermediates(tree) would in effect cause the above to become

(g (i 4) (i 5))

and the pseudo code for this IF the this pointer was reassignable would look like the following..

DTREE::removeIntermediates(){
    this = child(0); removeIntermediates();
}

TREE::removeIntermediates(){
    for each child { child->removeIntermediates();
}

I wanted to do this without knowing what the child node was therefore making code factorable into different functions for each node type and having a general function for other types. Sadly, I just ended up doing something like this..

TREE::removeIntermediates(){
    for each child { if(child->name == "d") {
        setchild(child->child(0));
        child->removeIntermediates();
    }
    else { child->removeIntermediates();}
}

回答1:

C++ standard forbids assignment to this in "9.3.2 The this pointer" by stating that "keyword this is a non-lvalue expression". Although, some compilers still allow assignment to this by using a certain compile-time switch, because at some point in early drafts C++ standard actually allowed assignment to "this".

Anyway, it is quite hard to imagine a case where you would actually want to do that and it is very likely that there is a clean and beautiful way to do it.



回答2:

No, this is not modifiable.

Conceptually that doesn't make sense, what are you trying to accomplish?



回答3:

No, you should never, ever, set this.

If you need to point to different objects then define your own variable.



回答4:

No. This is an rvalue, not an lvalue. The easiest way to think of it is that it invokes compiler magic to access the object on which the function was called. You can't modify it any more than you could modify the constant 3.

Historically, in very early versions of C++, you could modify it, but only in the constructor, and only as the first thing in the constructor: the functionality offered by this has been subsumed by user defined operator new. This was 20-15 years ago, however.

What are you trying to do? If you just want to access two different objects from the same member function, that's no problem: otherfooinstance-> should work, and will give you access to the private members as well.



回答5:

The member method void foo::bar() { this = otherfooinstance; } will be compile like this:

void foo__bar(foo * const this) { this = otherfooinstance; }

this is a const pointer to calling foo instance, so you can't change it. And change this is not a good idea.



回答6:

The "this" pointer doesn't really exist. That is, it's not stored somewhere with the object. Rather, when a method is called on an object the compiler passes the address of the object as an extra argument. So "this" only ever really appears on the stack while a method is executing.

So even if you did assign to "this" as in your example, your redirection to otherfooinstance would last only for the duration of the current bar() invocation.