0

In OOP: For efficient code maintenance, what is the standard best practice to "link" deep copy constructors, and deep copy through assignment operator (=), so that they perform consistently?

I want to be able to edit the copy logic in one place (say, the copy constructor), and for it to be changed also for the assignment operator.

My take would be the following:

class MyClass
{
private:
    int* _data;

    MyClass& _deep_copy(const MyClass& source)
    {   
        delete _data;
        _data = new int;
        *_data = *source._data;
        return *this; // assuming &source != this
    }

public:
    MyClass() : _data{nullptr} {}

    MyClass(const int data)
    {
        _data = new int;
        *_data = data;
    }

    MyClass(const MyClass& source)
    {
        _data = nullptr;
        _deep_copy(source);
    }
    MyClass& operator=(const MyClass& source)
    {
        return _deep_copy(source);
    }
};

Maybe there's a way to use some sort of "delegation"?

Thank you!

Michel H
  • 317
  • 3
  • 10
  • 2
    I wouldn't say there's any "correct way" to do it. Honestly it's always kind of a headache. Deferring things to another function causes non-fundamental types to be initialized twice during copy construction. Once before the constructor body is entered and then again when they're actually set. Additionally, there's the question of checking against `this` during copy assignment (which a lot of people skip because 99.9% of the time its an unnecessary branch) – AndyG Mar 15 '21 at 18:12
  • 3
    There is a fundamental difference between a copy constructor and a copy assignment operator. A copy constructor creates a new object and a copy assignment operator applies to an existing object. That `_deep_copy` member function operates on an existing object. Calling it from the body fo the copy constructor is legal, but all of the data members will have already been default-constructed before entering the body of the constructor, so there's more work being done than is necessary. – Pete Becker Mar 15 '21 at 18:13
  • 1
    I think this will depend a lot on opinions. In this example, one could consider dropping `_deep_copy` and move that code into the copy constructor, then use that in the copy assignment operator to first copy, then move assign: `MyClass& operator=(const MyClass& source) { *this = MyClass(source); return *this; }` – Ted Lyngmo Mar 15 '21 at 18:14
  • Hey guys! Good answers and opinions from all of you. Appreciate it! I like Ted's approach to reusing the copy constructor and then using move semantics. However this opens a new question: How do I optimize consistency between move assign / move constructor? – Michel H Mar 15 '21 at 19:14

0 Answers0