18
class C{
   //methods and properties
}

void C::some_method(C* b){
    delete this;
    this = b;     
}

This gives me follwing error when compiling:

error: lvalue required as left operand of assignment

My intention: Say there are objects a and b of class C. The contents of the class C can be very huge and field by field copying can be very costly. I want all the contents of 'a' to be replaced by 'b' in an economical way.

Will default copy constructor do the intended task?

I found something called 'move constructor' http://akrzemi1.wordpress.com/2011/08/11/move-constructor/

Perhaps, it might get the effect that I want.

Rndp13
  • 1,094
  • 1
  • 21
  • 35
Utkrist Adhikari
  • 1,052
  • 3
  • 15
  • 42

6 Answers6

24

The this-pointer is an implicit pointer to the object in whose context you are working, you cannot reassign it.

According to Stroustrup's bible (The C++ Programming Language, 3rd edition I have) this is expressed as

C * const this

meaning you have a constant pointer to your class C, so the compiler will complain if you try to change it.

EDIT:

As I was corrected, the above mentioned expression does not describe this fully correctly, for this is actually an rvalue.

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • I wasn't sure if `this` is const, thanks for the information. – EarlGrey Aug 14 '13 at 09:23
  • You can even go on top of this and have a `this`-pointer to a constant object, yielding `const C * const this` – bash.d Aug 14 '13 at 09:26
  • 1
    The quote says how it is "implemented". Formally, `this` is not an object; it is an rvalue expression. – James Kanze Aug 14 '13 at 09:39
  • @JamesKanze Thank you, where can I find further information about `this`, please? I corrected my post. – bash.d Aug 14 '13 at 09:59
  • @kol All right, but your approach is a hack exploiting some of the weaknesses of C++. After all we are talking about reassignment, not hacking... – bash.d Aug 14 '13 at 10:31
  • 1
    @kol No you can't. To change the value, you need some sort of lvalue expression. And since `this` is an rvalue, and doesn't have a class type, there's no way to get an lvalue from it. – James Kanze Aug 14 '13 at 10:51
  • @bash.d I got it from the standard. But that's not the text I'd recommend for beginners. (I'm sure that Bjarne wrote the above with the intent of giving a rough idea, so that a beginner could understand, and not with the idea of a normative text. And he might have been influenced by the compiler he wrote, which used C as an intermediate language, and probably generated something like this in the C.) – James Kanze Aug 14 '13 at 10:59
  • 1
    It is not `const`, it is an rvalue. The two are totally different thing. You can view them as somewhat equivalent in this case, but in general, they are not the same at all. – Puppy Aug 14 '13 at 12:56
  • 1
    @bash.d: James Kanze's answer clearly quotes the Standard on this issue. – Puppy Aug 14 '13 at 13:00
  • @bash.d: What, to save you the trouble of scrolling down and reading another answer? No. – Puppy Aug 14 '13 at 13:01
  • @DeadMG So, I corrected my post, will you revoke your downvote, please? – bash.d Aug 14 '13 at 13:32
15

You cannot change what this points to. I would also not know why you'd want to do this.

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • 2
    @kol Actually you can't, unless your compiler is seriously broken (or seriously old---you could up until a little before 1990, when the possibility of overloading `operator new` was added to the language). – James Kanze Aug 14 '13 at 11:09
14

To quote the standard:

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.

A "prvalue" is a pure rvalue, something like 42 or 3.14159. In the same way you can't do something like 42 = x, you can't assign to this; in both cases (at least conceptually), there is no object whose value can change.

And I'm really curious as to what you expect to happen if I write something like:

int
main()
{
    C c1;
    C c2
    c1.some_method( &c2 );
}

Do you expect the address of c1 to somehow miraculously change, and for c1 and c2 to be aliases to the same object? (And c1.some_method( NULL ) is even more intreguing.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 2
    @kol Actually, you cannot, and your answer is simply incorrect. The standard is quite clear here: `this` is a prvalue (or an rvalue in pre-C++11), and assignment to an rvalue is illegal, and there is _no_ way to get an lvalue from an rvalue of non-class type. – James Kanze Aug 14 '13 at 11:06
  • @JamesKanze Yes I want them to be aliases. – Utkrist Adhikari Aug 14 '13 at 11:19
  • @UtkristAdhikari But that's manifestly impossible, since the code in a member function cannot change the meaning of a symbol in `main`. In `main`, `c1` designates a very specific entity, and the association symbol -> entity is managed entirely by the compiler and the linker, at compile and link time. – James Kanze Aug 14 '13 at 11:22
6

You can't assign a different value to this as it point to the object itself, and this haven't any sense. You could instantiate a new object and use its implicit this pointer instead.

Moreover, if you try to make a copy of object, you can overwrite operator=

class Foo
{
  public:
    [...]
    Foo& operator=(const Foo& foo);
}

int main()
{
 Foo foo;
 foobar = foo; //invoke operator= overwrited method
}


DonCallisto
  • 29,419
  • 9
  • 72
  • 100
1

The error says "You can't assign b to this". As far as I know, this is something you can't change, because it's not an actual pointer, but a self-reference.

EarlGrey
  • 531
  • 7
  • 29
  • It's a pointer, it's basically `ClassType* const this`, which means it cannot be modified to point to something else, and since it's a prvalue it can't be on the lhs of an expression. – Rapptz Aug 14 '13 at 10:43
  • 2
    @Rapptz It has a pointer type, but it _isn't_ const, since it is an rvalue, and rvalues of non-class type don't have cv-qualifiers. – James Kanze Aug 14 '13 at 11:07
  • What is another example of an rvalue of non-class type? – Samuel Danielson Mar 06 '16 at 17:11
1

Just use the usual approach instead of black magic and UB:

C* c1 = new C();
C* c2 = new C();

// do some work perhaps ...

delete c1;
c1 = c2;

Now c1 is an alias to c2 as you wanted. Be careful though when cleaning up memory so you don't end up deleting an object twice. You might perhaps consider smart pointers...

PeterK
  • 6,287
  • 5
  • 50
  • 86
  • the assignment must happen inside the method of c1 – Utkrist Adhikari Aug 14 '13 at 11:53
  • This code is not the usual approach for anything. If you just wanted c1 to point to the same object as c2, there's no reason to new and delete an object for c1. Just assign c2 to c1 straight away. Furthermore, naked new and delete are not exception safe (exception safety is important even if you're not using the built-in C++ exception-handling mechanism). At the very least, use a unique_ptr to hold your dynamically allocated object. But unless you have a good reason, you should not be dynamically allocating in the first place. The usual approach to create an alias is through a reference. – suncho Jul 15 '17 at 03:22