Search code examples
c++copy-constructorcopy-assignment

why is the copy constructor being called before copy assignment?


class LinkedList
{
public:
    LinkedList() : _head(nullptr) {}
    LinkedList(ListElement *newElement) : _head(newElement) {}
    ~LinkedList() {  };
    LinkedList(const LinkedList& LL);
    LinkedList& operator=(LinkedList byValLinkedList);
private:
    ListElement *_head;
}
LinkedList::LinkedList(const LinkedList & LL)
{
    ListElement *curr = LL._head;

    // If Linked List is empty
    if (isEmpty() && curr != nullptr) {
        _head = new ListElement(curr->getValue());
        curr = curr->getNext();
    }

    ListElement *newNode = nullptr;
    while (curr) {
        newNode = new ListElement(curr->getValue());
        curr = curr->getNext();
    }
}

LinkedList& LinkedList::operator=(LinkedList byValLinkedList)
{

std::swap(_head, byValLinkedList._head);
return *this;
}


int main() {
    using namespace std;
    LinkedList LL1(new ListElement(7));
    //..... some insertions
    LinkedList LL2(new ListElement(5));
    //..... some insertions
    LL1 = LL2;  // What is the order ?
    // ..... do something else
    return 0;
}

When LL1 = LL2 is executed, which one is supposed to be called.

I expect the copy-assignment to happen. But the code was executed in the following order

  1. Copy Constructor
  2. Copy-Assignemnt
  3. Destructor

What am i doing wrong ? and why was the destructor called?


Solution

  •  LinkedList& operator=(LinkedList byValLinkedList);
    

    Your copy assignment takes its parameter by value. This means that

     LL1=LL2;
    

    needs to make a copy of LL2, in order to pass it by value. That's what "passing by value" means. Hence, the copy constructor.

    To avoid doing copy construction, the assignment operator must take its parameter by reference, instead:

     LinkedList& operator=(const LinkedList &byValLinkedList);
    

    That means, if course, you can't quite implement the assignment operator using std::swap. But that would be a different question...

    Briefly, you have two options: either implement two copy constructors, one that takes a const reference and one that does not, with the latter being able to use std::swap. Or, declare _head to be mutable.