0

I'm attempting to call my copy constructor in my assignment operator overload. I assign the result of the copy constructor to a pointer called temp, then set the this pointer to equal temp. This results gives me the error: lvalue required as left operand of assignment. I thought this was a pointer to my object. Why is there an issue with reassigning the pointer to a different object?

In the passing case I defereence this(*this) and set it equal to temp. To me this means I'm saying the actual object is equal to a pointer. Am I misinterpreting the meaning of this?

Passing case:

Foo *temp = new Foo(other); //invokes copy constructor
*this = temp;

Failing case:

Foo *temp = new Foo(other); //invokes copy constructor
this = temp;

Full source code:

TreeNode::TreeNode(TreeNode *other) {
    this->leftChild = other->leftChild;
    this->rightChild = other->rightChild;
    this->data = other->data;
}

TreeNode& TreeNode::operator=(TreeNode *other) {
    if(this != other) {
        TreeNode *temp = new TreeNode(other);
        this = temp;
    }
    return *this;
}
  • 1
    *Proper* copy constructors and copy assignment operators don't take pointers as input, they take references instead. And `this` is a const pointer, you can't reassign it – Remy Lebeau Oct 04 '19 at 01:55
  • For `TreeNode` you don't need to write copy constructor and assignment operator at all. Compiler-generated ones will suffice. – Eugene Oct 04 '19 at 03:17

1 Answers1

1

1) this is a built-in rvalue expression that every class has (meaning it cannot be modified as per C++ standard), and it always points to the instance of the class (the object) making the function call.

2) *this is always an lvalue, i.e. it must have an address in memory, i.e. it represents an object that can be modified.

So when you dereference this:

*this = temp

You have an lvalue, affiliated with a space in memory, but not with

this = temp

For a detailed discussion of rvalues and this:

What is "rvalue reference for *this"?

Type of 'this' pointer

As is, this code seems a bit problematic. Consider what happens when you do something like:

treenode1 = treenode2;  //assuming both are pointers to TreeNode objects

The compiler sees the lvalue treenode1 (to whose object 'this' will always refer during the operation), then sees the '=', notes the overload, then uses pointer treenode2 to create a NEW copy of the object treenode2 is pointing to (binding the lvalue temp to the new object), then tries to copy the values in temp over into the original treenode1-bound object (we have three TreeNodes now existing, I believe).

What you don't want is to have that temp object hanging around after this convoluted operation is done, I believe, as that would cause a memory leak. So you'd need to delete it before. So if you absolutely had to do this for some reason, the solution is a move assignment operator, which is designed for use with temporary objects. Probably best to avoid this pattern altogether however, it seems very liable to give memory leaks.

neutrino_logic
  • 1,239
  • 1
  • 4
  • 11