-1

I'm trying to implement treap class, so I have this code:

void item::insert(item* it) {
     if (!this)
         this = it;
     .....

I can't compile this with GCC:

error: lvalue required as left operand of assignment

I know, I can simply assign all members of it to this, but is there another way?

miloserdow
  • 1,051
  • 1
  • 7
  • 27

2 Answers2

5

As per §9.3.2/1:

In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called.

Therefore the this pointer can never be nullptr within a non-static member function, assuming the object, from which the member function is invoked, has been allocated correctly (in the case the member function is invoked on a null pointer, the behavior seems to be undefined).

And second: don't try to change the this pointer, because it's not assignable. For good reasons.

Community
  • 1
  • 1
Shoe
  • 74,840
  • 36
  • 166
  • 272
  • 1
    You are wrong. this can be equal to nullptr within a non-static member function.. – Vlad from Moscow May 03 '14 at 11:05
  • @VladfromMoscow, you make me curious. I assume you can always assign to this after casting away the const and set it null, but apart from that? – Peter - Reinstate Monica May 03 '14 at 11:08
  • Would you care to elaborate about the reasons? – Peter - Reinstate Monica May 03 '14 at 11:09
  • 1
    @Peter Schneider this is not const. It is an rvalue. If a member function does not access any data member then you can write ( (YourClass *)NULL )->MemberFunction(); In this case inside the function this will be equal to NULL. – Vlad from Moscow May 03 '14 at 11:10
  • 3
    @VladfromMoscow you are wrong, that's just undefined behavior. The only way to reach a situation where `this == NULL` is through undefined behavior, so invalid. – Luchian Grigore May 03 '14 at 11:16
  • @Luchian Grigore I pointed out that such a possibility exists that inside a non-static member function this can be equal to nullptr. – Vlad from Moscow May 03 '14 at 11:18
  • @VladfromMoscow you might as well have pointed out that inside a non-static member function `1 == 2` might yield `true` - it can happen if it follows undefined behavior. – Luchian Grigore May 03 '14 at 11:19
  • @Luchian Grigore I do not see undefined behaviour. The undefined behaviour corresponds only the case when you use this to access data members. When a member function is called this is simply used as the first implicit argument. So there is defined behaviour. – Vlad from Moscow May 03 '14 at 11:21
  • @VladfromMoscow Interesting.-- const: The IBM docs said that "The type of the this pointer for a member function of a class type X, is X* const." (http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr035.htm) but I see that the new standard defines it the way you said. – Peter - Reinstate Monica May 03 '14 at 11:24
  • @VladfromMoscow http://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-beha I thought you already knew this... – Luchian Grigore May 03 '14 at 11:25
  • @Peter Schneider Are you deal with an IBM mainframe? – Vlad from Moscow May 03 '14 at 11:26
  • @LuchianGrigore You may be right that calling a member function on a null pointer is UB, but it is indeed important to understand that it can nevertheless happen, and that `this` may actually be null when the member function is entered. If you forget about this **technical** possibility while you are debugging a program in which it occurs, you will be hard put to understand what is going on. – cmaster - reinstate monica May 03 '14 at 11:26
  • @cmaster - it annoys me that many, (most) debuggers do not display 'this' when entering a member function. I've now got quite good at spotting a null or illegal 'this', but it should be easier! Usually, the only clue is when the function segfaults/AV when reading a member var that you KNOW has been initialised correctly. – Martin James May 03 '14 at 11:29
  • @cmaster there's a **technical** posiblity for **anything** to happen after UB. – Luchian Grigore May 03 '14 at 11:32
  • Well, it would be nice if the debugger told me that something bad is likely to happen before I have to put a net over my nose to catch the demons. – Martin James May 03 '14 at 11:33
  • @LuchianGrigore Where is it specified that Vlad's code is UB? (As opposed to e.g. IDB). I'm really not sure where even to look int the standard. – Peter - Reinstate Monica May 03 '14 at 11:40
  • @MartinJames I'm entirely with you that this would be a *very* nice debugger feature :-) – cmaster - reinstate monica May 03 '14 at 13:05
  • @PeterSchneider Calling a member function on a pointer counts as dereferencing the pointer afaik, hence it is UB if that pointer is a null pointer. After all, if the member function is virtual, the pointer *is technically dereferenced and will segfault immediately*. The problem is that this segfault may even be deferred until **after** the call completes in the nonvirtual case (this is the case with accessors that only return a reference to a member which is not dereferenced until the caller accesses the object behind that reference, which may again defer...). This can be a real mess to debug. – cmaster - reinstate monica May 03 '14 at 13:14
1

I know, I can simply assign all members of it to this, but is there another way?

You are looking for *this = *it. this is not an lvalue.


You should probably take an item const& rather than an item*:

void item::insert(item const& it) {
    *this = it;
}

As a side note: this can never be the null pointer in any well-defined program, since methods can only be called on objects. The null pointer doesn’t point to an object.