Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

so what is the type of "this" ? Why is "this" not a lvalue?

Tags:

c++

Say the object is

class A {
public :  void Silly(){
    this = 0x12341234;
}

I know I will get compiler error ' "this" is not a lvalue.' But then it is not a temporary either. So what is the hypothetical declaration of "this" ?

Compiler : GCC 4.2 compiler on mac.

like image 539
Ajeet Ganga Avatar asked Sep 07 '11 23:09

Ajeet Ganga


5 Answers

For some class X, this has the type X* this;, but you're not allowed to assign to it, so even though it doesn't actually have the type X *const this, it acts almost like it was as far as preventing assignment goes. Officially, it's a prvalue, which is the same category as something like an integer literal, so trying to assign to it is roughly equivalent to trying to assign a different value to 'a' or 10.

Note that in early C++, this was an lvalue -- assigning to this was allowed -- you did that to handle the memory allocation for an object, vaguely similar to overloading new and delete for the class (which wasn't supported yet at that time).

like image 127
Jerry Coffin Avatar answered Oct 16 '22 09:10

Jerry Coffin


It is impossible to provide a "declaration" for this. There's no way to "declare" an rvalue in C++. And this is an rvalue, as you already know.

Lvalueness and rvalueness are the properties of expressions that produce these values, not the properties of declarations or objects. In that regard, one can even argue that it impossible to declare an lvalue either. You declare an object. Lvalue is what is produced when you use the name of that object as an expression. In that sense both "to declare an rvalue" and "to declare an lvalue" are oxymoron expressions.

Your question also seems to suggest that the properties of "being an lvalue" and "being a temporary" are somehow complementary, i.e. everything is supposedly an lvalue or a temporary. In reality, the property of "being a temporary" has no business being here. All expressions are either lvalues or rvalues. And this happens to be an rvalue.

Temporaries, on the other hand, can be perceived as rvalues or as lvalues, depending on how you access the temporary.

P.S. Note, BTW, that in C++ (as opposed to C) ordinary functions are lvalues.

like image 29
AnT Avatar answered Oct 16 '22 08:10

AnT


For one thing, this is not a variable - it's a keyword. When used as a rvalue, its type is A * or A const *. In modern C++, assigning to this is prohibited. You cannot take the address of this, either. In other words, it's not a valid lvalue.

like image 25
Seva Alekseyev Avatar answered Oct 16 '22 10:10

Seva Alekseyev


To answer the second part, "why is this not an lvalue", I'm speculating as to the committee's actual motivation, but advantages include:

  1. assigning to this doesn't make much logical sense, so there's no particular need for it to appear on the left-hand-side of assignments. Making it an rvalue emphasises that this doesn't make much sense by forbidding it, and means that the standard doesn't have to define what happens if you do it.
  2. making it an rvalue prevents you taking a pointer to it, which in turn relieves the implementation of any need to furnish it with an address, just like a register-modified automatic variable. It could for example devote a register in non-static member functions to storing this. If you take a const reference, then unless the use permits cunning optimization it needs to be copied somewhere that has an address, but at least it needn't be the same address if you do it twice in quick succession, as it would need to be if this were a declared variable.
like image 2
Steve Jessop Avatar answered Oct 16 '22 09:10

Steve Jessop


You get a compiler error because this is a const pointer to the instance of the class of the same type as that class. You can't assign to it although you can use it to change other class members in non-const qualified methods, call methods, and operators. Also note because it's an instance that static methods do not have a this pointer.

Hypothetical:

class Whatever
{
    // your error because this is Whatever* const this;
    void DoWhatever(const Whatever& obj) { this = &obj; } 

    // this is ok
    void DoWhatever(const Whatever& obj) { *this = obj; }

    // error because this is now: const Whatever* const this;
    void DoWhatever(const Whatever& obj) const { *this = obj; } 

    // error because this doesn't exist in this scope
    static void DoWhatever(const Whatever& obj) { *this = obj; }
};
like image 1
AJG85 Avatar answered Oct 16 '22 10:10

AJG85