NightFurry
NightFurry

Reputation: 358

Why not only one? Copy constructor and assignment operator

I understand which is invoked in what situation...

Sample a;
Sample b = a; //calls copy constructor
Sample c;
c = a;        //calls assignment operator

My question is Why these 2 different things exist at all? Why can't only one of the two take care of both situations?

Upvotes: 5

Views: 1489

Answers (5)

Vinh Dat Ha
Vinh Dat Ha

Reputation: 57

Basically, they are used in different situations, many correct answer, i just wanna add something to clear out where the copy constructor is also used:

For example:

void test(Fraction in){
    //Do something here
    }

Fraction test2(){
    Fraction a(1, 2);
    //Do something here
    return a; // construct a return value by copy a
}

int main()
{
    Fraction a(2, 3);
    Fraction b(a); //construct b by copy a
    Fraction c=a; //construct c by copy a
    test(a); //construct in by copy a
}

Upvotes: 0

Stian Svedenborg
Stian Svedenborg

Reputation: 1825

Well, you could technically get away with just having a copy-constructor and a destructor, but that would require that every time you wanted to do an assignment you would have to destroy the object and then reconstruct it. This would become HIGHLY inefficient in the vast majority of use cases.

We cannot just have an operator= either, as you have no idea what the left-hand-side of the operator will be if it has not yet been constructed. It's members would probably contain garbage data and "shit would hit the fan".

Thus, you can think of the need for both an operator= and a copy-constructor as an optimization.


That being said there are a few design-patterns that can reduce the amount of code you have to write. For example, assuming you have a copy-constructor, a destructor and a swap-function implemented for your class. You could implement operator= using a copy-swap operation:

MyClass & operator=( MyClass rhs ) { // notice the call by value, this will 
                                     // implicitly call the copy-constructor.
    swap(*this, rhs);
    return *this;
}

Whilst this operator has strong exception safety, it is worth to notice that it may be much less efficient than reusing preallocated resources (which a more advanced operator= might do).

Upvotes: 0

ikh
ikh

Reputation: 10417

Suppose the String class:

class String
{
    char *m_str;
    size_t m_len, m_alloced;
public:
    String(const char *str = "")
    {
        m_len = strlen(str);
        m_alloced = m_len + 1;
        m_str = (char *)malloc(m_alloced);
        strcpy(m_str, str);
    }
    String(const String &other)
    {
        m_len = other.m_len;
        m_alloced = m_len + 1;
        m_str = (char *)malloc(m_alloced);
        strcpy(m_str, other.m_str);
    }
    String &operator =(const String &rhs)
    {
        if (m_alloced < rhs.m_len + 1)
        {
            m_alloced = rhs.m_len + 1;
            m_str = (char *)realloc(m_str, m_alloced);
        }

        m_len = rhs.m_len;
        strcpy(m_str, rhs.m_str);
        return *this;
    }
    const char *get() const
    {
        return m_str;
    }
};

(live example)

Appearently, copy constructor and copy assignment operator does different things. Look at the String::String(const String &other).

m_len = other.m_len;
m_alloced = m_len + 1;
m_str = (char *)malloc(m_alloced);
strcpy(m_str, other.m_str);

It initializes its object. Set m_len, m_alloced, and m_str, and strcpy the string.

However, the String &String::operator =(const String &rhs) does -

if (m_alloced < rhs.m_len + 1)
{
    m_alloced = rhs.m_len + 1;
    m_str = (char *)realloc(m_str, m_alloced);
}

m_len = rhs.m_len;
strcpy(m_str, rhs.m_str);
return *this;

modify its object. Allocate more memory if required, and reset m_len and recopy the string.

Copy constructor is called when the object is created, and does initialize its object.

But copy assignment operator is called after the object is created, and does modify its object.


For example, look at this code.

String str1 = "asdf";
String str2 = str1;
String str3 = "12";
str3 = str1;

(it's also in the live example)

str1 is initialized by String::String(const char *). As you know, it'll contain "asdf".

str2 is initialized by copy constructor, String::String(const String &other). By the copy constructor, str2 will contain the same content.

str3 is initialized by String::String(const char *), like str1. However, in line 4, it is modified by copy assignment operator. So, str3 contains "12" at first, but its content will be modified into "asdf", by copy assignment operator.

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172964

No, they are different.

Copy constructor is used for constructing a new object (from another object). In this case you just need to initialize the members.

Assignment operator is used for an existing object (you may have constructed it by default constructor etc), and then assign it by another object. In this case you need to re-initialize members, sometimes means destroying and initializing them again.

Even so, the functionality of them are so similar, so you can share their implementation usually. Such as: What is the copy-and-swap idiom?

Upvotes: 6

hahcho
hahcho

Reputation: 1409

The copy constructor is invoked on creation, that means you don't have to take care of old resources in your object. The assignment operator on the other hand has to free the old resources. Besides they have different semantical meaning.

Upvotes: 2

Related Questions