• Graphics and multimedia
  • Language Features
  • Unix/Linux programming
  • Source Code
  • Standard Library
  • Tips and Tricks
  • Tools and Libraries
  • Windows API
  • Copy constructors, assignment operators,

Copy constructors, assignment operators, and exception safe assignment

*

Learn C++

21.13 — Shallow vs. deep copying

Shallow copying

Because C++ does not know much about your class, the default copy constructor and default assignment operators it provides use a copying method known as a memberwise copy (also known as a shallow copy ). This means that C++ copies each member of the class individually (using the assignment operator for overloaded operator=, and direct initialization for the copy constructor). When classes are simple (e.g. do not contain any dynamically allocated memory), this works very well.

For example, let’s take a look at our Fraction class:

The default copy constructor and default assignment operator provided by the compiler for this class look something like this:

Note that because these default versions work just fine for copying this class, there’s really no reason to write our own version of these functions in this case.

However, when designing classes that handle dynamically allocated memory, memberwise (shallow) copying can get us in a lot of trouble! This is because shallow copies of a pointer just copy the address of the pointer -- it does not allocate any memory or copy the contents being pointed to!

Let’s take a look at an example of this:

The above is a simple string class that allocates memory to hold a string that we pass in. Note that we have not defined a copy constructor or overloaded assignment operator. Consequently, C++ will provide a default copy constructor and default assignment operator that do a shallow copy. The copy constructor will look something like this:

Note that m_data is just a shallow pointer copy of source.m_data, meaning they now both point to the same thing.

Now, consider the following snippet of code:

While this code looks harmless enough, it contains an insidious problem that will cause the program to exhibit undefined behavior!

Let’s break down this example line by line:

This line is harmless enough. This calls the MyString constructor, which allocates some memory, sets hello.m_data to point to it, and then copies the string “Hello, world!” into it.

This line seems harmless enough as well, but it’s actually the source of our problem! When this line is evaluated, C++ will use the default copy constructor (because we haven’t provided our own). This copy constructor will do a shallow copy, initializing copy.m_data to the same address of hello.m_data. As a result, copy.m_data and hello.m_data are now both pointing to the same piece of memory!

When copy goes out of scope, the MyString destructor is called on copy. The destructor deletes the dynamically allocated memory that both copy.m_data and hello.m_data are pointing to! Consequently, by deleting copy, we’ve also (inadvertently) affected hello. Variable copy then gets destroyed, but hello.m_data is left pointing to the deleted (invalid) memory!

Now you can see why this program has undefined behavior. We deleted the string that hello was pointing to, and now we are trying to print the value of memory that is no longer allocated.

The root of this problem is the shallow copy done by the copy constructor -- doing a shallow copy on pointer values in a copy constructor or overloaded assignment operator is almost always asking for trouble.

Deep copying

One answer to this problem is to do a deep copy on any non-null pointers being copied. A deep copy allocates memory for the copy and then copies the actual value, so that the copy lives in distinct memory from the source. This way, the copy and source are distinct and will not affect each other in any way. Doing deep copies requires that we write our own copy constructors and overloaded assignment operators.

Let’s go ahead and show how this is done for our MyString class:

As you can see, this is quite a bit more involved than a simple shallow copy! First, we have to check to make sure source even has a string (line 11). If it does, then we allocate enough memory to hold a copy of that string (line 14). Finally, we have to manually copy the string (lines 17 and 18).

Now let’s do the overloaded assignment operator. The overloaded assignment operator is slightly trickier:

Note that our assignment operator is very similar to our copy constructor, but there are three major differences:

  • We added a self-assignment check.
  • We return *this so we can chain the assignment operator.
  • We need to explicitly deallocate any value that the string is already holding (so we don’t have a memory leak when m_data is reallocated later). This is handled inside deepCopy().

When the overloaded assignment operator is called, the item being assigned to may already contain a previous value, which we need to make sure we clean up before we assign memory for new values. For non-dynamically allocated variables (which are a fixed size), we don’t have to bother because the new value just overwrites the old one. However, for dynamically allocated variables, we need to explicitly deallocate any old memory before we allocate any new memory. If we don’t, the code will not crash, but we will have a memory leak that will eat away our free memory every time we do an assignment!

The rule of three

Remember the rule of three? If a class requires a user-defined destructor, copy constructor, or copy assignment operator, then it probably requires all three. This is why. If we’re user-defining any of these functions, it’s probably because we’re dealing with dynamic memory allocation. We need the copy constructor and copy assignment to handle deep copies, and the destructor to deallocate memory.

A better solution

Classes in the standard library that deal with dynamic memory, such as std::string and std::vector, handle all of their memory management, and have overloaded copy constructors and assignment operators that do proper deep copying. So instead of doing your own memory management, you can just initialize or assign them like normal fundamental variables! That makes these classes simpler to use, less error-prone, and you don’t have to spend time writing your own overloaded functions!

  • The default copy constructor and default assignment operators do shallow copies, which is fine for classes that contain no dynamically allocated variables.
  • Classes with dynamically allocated variables need to have a copy constructor and assignment operator that do a deep copy.
  • Favor using classes in the standard library over doing your own memory management.

guest

Tech Differences

Know the Technical Differences

Difference Between Copy Constructor and Assignment Operator in C++

Copy-constructor-assignment-operator

Let us study the difference between the copy constructor and assignment operator.

Content: Copy Constructor Vs Assignment Operator

Comparison chart.

  • Key Differences

Definition of Copy Constructor

A “copy constructor” is a form of an overloaded constructor . A copy constructor is only called or invoked for initialization purpose. A copy constructor initializes the newly created object by another existing object.

When a copy constructor is used to initialize the newly created target object, then both the target object and the source object shares a different memory location. Changes done to the source object do not reflect in the target object. The general form of the copy constructor is

If the programmer does not create a copy constructor in a C++ program, then the compiler implicitly provides a copy constructor. An implicit copy constructor provided by the compiler does the member-wise copy of the source object. But, sometimes the member-wise copy is not sufficient, as the object may contain a pointer variable.

Copying a pointer variable means, we copy the address stored in the pointer variable, but we do not want to copy address stored in the pointer variable, instead, we want to copy what pointer points to. Hence, there is a need of explicit ‘copy constructor’ in the program to solve this kind of problems.

A copy constructor is invoked in three conditions as follow:

  • Copy constructor invokes when a new object is initialized with an existing one.
  • The object passed to a function as a non-reference parameter.
  • The object is returned from the function.

Let us understand copy constructor with an example.

In the code above, I had explicitly declared a constructor “copy( copy &c )”. This copy constructor is being called when object B is initialized using object A. Second time it is called when object C is being initialized using object A.

When object D is initialized using object A the copy constructor is not called because when D is being initialized it is already in the existence, not the newly created one. Hence, here the assignment operator is invoked.

Definition of Assignment Operator

The assignment operator is an assigning operator of C++.  The “=” operator is used to invoke the assignment operator. It copies the data in one object identically to another object. The assignment operator copies one object to another member-wise. If you do not overload the assignment operator, it performs the bitwise copy. Therefore, you need to overload the assignment operator.

In above code when object A is assigned to object B the assignment operator is being invoked as both the objects are already in existence. Similarly, same is the case when object C is initialized with object A.

When the bitwise assignment is performed both the object shares the same memory location and changes in one object reflect in another object.

Key Differences Between Copy Constructor and Assignment Operator

  • A copy constructor is an overloaded constructor whereas an assignment operator is a bitwise operator.
  • Using copy constructor you can initialize a new object with an already existing object. On the other hand, an assignment operator copies one object to the other object, both of which are already in existence.
  • A copy constructor is initialized whenever a new object is initialized with an already existing object, when an object is passed to a function as a non-reference parameter, or when an object is returned from a function. On the other hand, an assignment operator is invoked only when an object is being assigned to another object.
  • When an object is being initialized using copy constructor, the initializing object and the initialized object shares the different memory location. On the other hand, when an object is being initialized using an assignment operator then the initialized and initializing objects share the same memory location.
  • If you do not explicitly define a copy constructor then the compiler provides one. On the other hand, if you do not overload an assignment operator then a bitwise copy operation is performed.

The Copy constructor is best for copying one object to another when the object contains raw pointers.

Related Differences:

  • Difference Between & and &&
  • Difference Between Recursion and Iteration
  • Difference Between new and malloc( )
  • Difference Between Inheritance and Polymorphism
  • Difference Between Constructor and Destructor

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Copy constructors and copy assignment operators (C++)

  • 8 contributors

Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment . In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++) .

Both the assignment operation and the initialization operation cause objects to be copied.

Assignment : When one object's value is assigned to another object, the first object is copied to the second object. So, this code copies the value of b into a :

Initialization : Initialization occurs when you declare a new object, when you pass function arguments by value, or when you return by value from a function.

You can define the semantics of "copy" for objects of class type. For example, consider this code:

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows:

Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x); .

Use the copy constructor.

If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you. Similarly, if you don't declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor doesn't suppress the compiler-generated copy assignment operator, and vice-versa. If you implement either one, we recommend that you implement the other one, too. When you implement both, the meaning of the code is clear.

The copy constructor takes an argument of type ClassName& , where ClassName is the name of the class. For example:

Make the type of the copy constructor's argument const ClassName& whenever possible. This prevents the copy constructor from accidentally changing the copied object. It also lets you copy from const objects.

Compiler generated copy constructors

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name ." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name & . In such a case, the compiler-generated copy constructor's argument is also const .

When the argument type to the copy constructor isn't const , initialization by copying a const object generates an error. The reverse isn't true: If the argument is const , you can initialize by copying an object that's not const .

Compiler-generated assignment operators follow the same pattern for const . They take a single argument of type ClassName& unless the assignment operators in all base and member classes take arguments of type const ClassName& . In this case, the generated assignment operator for the class takes a const argument.

When virtual base classes are initialized by copy constructors, whether compiler-generated or user-defined, they're initialized only once: at the point when they are constructed.

The implications are similar to the copy constructor. When the argument type isn't const , assignment from a const object generates an error. The reverse isn't true: If a const value is assigned to a value that's not const , the assignment succeeds.

For more information about overloaded assignment operators, see Assignment .

Was this page helpful?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

  • C++ Classes and Objects
  • C++ Polymorphism
  • C++ Inheritance
  • C++ Abstraction
  • C++ Encapsulation
  • C++ OOPs Interview Questions
  • C++ OOPs MCQ
  • C++ Interview Questions
  • C++ Function Overloading
  • C++ Programs
  • C++ Preprocessor
  • C++ Templates
  • Types of Operator Overloading in C++
  • Overloading of function-call operator in C++
  • Overloading New and Delete operator in c++
  • Operator Overloading in C++
  • Typecast Operator Overloading in C++
  • Increment (++) and Decrement (--) Operator Overloading in C++
  • Overloading stream insertion (<>) operators in C++
  • Rules for operator overloading
  • Overloading Relational Operators in C++
  • Input/Output Operators Overloading in C++
  • C++ Assignment Operator Overloading
  • C++ Bitwise Operator Overloading
  • How to Overload == Operator in C++?
  • Different ways of Method Overloading in Java
  • Operator Overloading in Dart
  • Operator Overloading in Ruby
  • Operator Overloading in Julia
  • Kotlin Operator Overloading
  • Method Overloading in Different Classes in Java

Different Ways of Operator Overloading in C++

In C++, operator overloading is the concept that allows us to redefine the behavior of the already existing operator for our class. C++ provides a special function called operator function that can be used to achieve operator overloading.

In this article, we will learn the different ways in which we can define the operator function for operator overloading in C++.

We can define the operator function as the following three functions:

  • Operator Overloading using Friend Function
  • Operator Overloading using Member Function
  • Operator Overloading using Global Non-Friend Function

1. Operator Overloading Using Friend Function

Similar to the above approach where we defined the overload function outside the class definition, we can define that function as a friend when we want our operator function to modify the value of the private data members.

Again, the binary operator function will take two arguments and the unary operator function will take one argument as the function is defined outside the class and there will be no this pointer.

Note: Apart from the case where we need the operator function to give access to the private memebers, we should not use the friend function to prevent the exposure of private members to public API.

E xample of Operator Overloading Using Friend Function

Operators that cannot be overloaded when declaring that function as friend function are = () [] -> .

2. Overloading Operator Using Member Function

In this method, we create a member operator function defined inside the class. It is one of the simplest and most straightforward methods of operator overlading.

Here, the operator function takes one less argument as compared to the global operator overloads. For the binary operator, one argument will be the *this object, and the other will be taken as an argument. For unary, only * this object will be used.

Note: The operator function must ber a non-static (member function)

Example of Overloading Operator Using Non-Static Member Function

Explanation: In the above program, it shows that no argument is passed and no return_type value is returned, because the unary operator works on a single operand. (-) operator changes the functionality to its member function. For the (+) operator, one argument was passed and it returned an object of the same type with values of them added.

Note:  d2 = -d1 will not work, because operator-() does not return any value.

3. Overloading Operator Using Global Function

We can also overload an operator as the global function which is not a friend of the class. The compiler will find the overload by matching the types of the argument. If there are multiple matching operator overloads, then it will throw an ambiguity error.

Now, the global binary operator function will take two arguments, while the global unary operator function will take a single argument.

Example of Overloading Operator Using Global Function

Explanation: Here, d1 calls the operator function of its class object and takes d2 as a parameter, by which the operator function returns the object and the result will reflect in the d3 object.

It is generally preferred to overload binary operator as global function. It is because in global function, both the object or the value that can be converted to the object can be used as either left or right operand and it will work. For member operator function, it won’t work if the value that can be converted to object is used as left operand. For Example,

We overload the relational operator < for our class, then

Please Login to comment...

Similar reads.

  • cpp-overloading

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

COMMENTS

  1. c++

    The assignment operator is used to change an existing instance to have the same values as the rvalue, which means that the instance has to be destroyed and re-initialized if it has internal dynamic memory. Useful link : Copy Constructors, Assignment Operators, and More. Copy constructor and = operator overload in C++: is a common function possible?

  2. Copy Constructor vs Assignment Operator in C++

    C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Consider the following C++ program. Explanation: Here, t2 = t1; calls the assignment operator, same as t2.operator= (t1); and Test t3 = t1; calls the copy constructor ...

  3. c++

    Copy constructor is called when a new object is created from an existing object, as a copy of the existing object. And assignment operator is called when an already initialized object is assigned a new value from another existing object. Example-. t2 = t1; // calls assignment operator, same as "t2.operator=(t1);"

  4. 21.12

    21.12 — Overloading the assignment operator. Alex November 27, 2023. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. As of C++11, C++ also supports "Move assignment". We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

  5. Copy assignment operator

    Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type. [] NoteIf both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move), and selects the copy assignment if the argument is an ...

  6. Copy constructors and copy assignment operators (C++)

    Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x);. Use the copy constructor. If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you.

  7. Copy constructors, assignment operators,

    The first line runs the copy constructor of T, which can throw; the remaining lines are assignment operators which can also throw. HOWEVER, if you have a type T for which the default std::swap() may result in either T's copy constructor or assignment operator throwing, you are

  8. Copy constructors

    The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided ), which includes. initialization: T a = b; or T a(b);, where b is of type T ;

  9. PDF Constructors and Assignment

    operator overload. Copy Assignment Implementing the copy assignment operator is tricky for a couple of reasons: ... A default constructor, copy constructor, and copy assignment operator will all be defined for you if you don't define them. To prevent this, you can declare them in the

  10. When should we write our own assignment operator in C++?

    1) Do not allow assignment of one object to other object. We can create our own dummy assignment operator and make it private. 2) Write your own assignment operator that does deep copy. Same is true for Copy Constructor. Following is an example of overloading assignment operator for the above class. #include<iostream>.

  11. 14.14

    The rule of three is a well known C++ principle that states that if a class requires a user-defined copy constructor, destructor, or copy assignment operator, then it probably requires all three. In C++11, this was expanded to the rule of five , which adds the move constructor and move assignment operator to the list.

  12. PDF Copy Constructors and Assignment Operators

    using the copy constructor. What C++ Does For You Unless you specify otherwise, C++ will automatically provide objects a basic copy constructor and assignment operator that simply invoke the copy constructors and assignment operators of all the class's data members. In many cases, this is exactly what you want. For example, consider the ...

  13. C++ at Work: Copy Constructors, Assignment Operators, and More

    Figure 1 Copy Constructors and Assignment Operators // cctest.cpp: Simple program to illustrate a problem calling // operator= from copy constructor. ... This has the added benefit that gcnew doesn't collide with C++ new, which can be overloaded or even redefined as a macro. C++/CLI has many other cool features designed to make interoperability ...

  14. 21.13

    Shallow copying. Because C++ does not know much about your class, the default copy constructor and default assignment operators it provides use a copying method known as a memberwise copy (also known as a shallow copy ). This means that C++ copies each member of the class individually (using the assignment operator for overloaded operator=, and ...

  15. Copy Constructor in C++

    A copy constructor is called when a new object is created from an existing object, as a copy of the existing object. The assignment operator is called when an already initialized object is assigned a new value from another existing object. In the above example (1) calls the copy constructor and (2) calls the assignment operator.

  16. Difference Between Copy Constructor and Assignment Operator in C++

    Copy constructor and assignment operator, are the two ways to initialize one object using another object. The fundamental difference between the copy constructor and assignment operator is that the copy constructor allocates separate memory to both the objects, i.e. the newly created target object and the source object. The assignment operator allocates the same memory location to the newly ...

  17. c++

    The assignment operator isn't a constructor at all, but an ordinary member funcion that can only be invoked on an existing object. Its purpose is to assign to your object the semantics of another object, so that after the assignment the two are semantically identical. You are not usually "overloading" the assignment operator, you are just ...

  18. C++ Assignment Operator Overloading

    The assignment operator,"=", is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types. Assignment operator overloading is binary operator overloading. Overloading assignment operator in C++ copies all values of one object to another object.

  19. Copy constructors and copy assignment operators (C++)

    Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment. In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see

  20. c++

    Q1. When you return a reference to an object, then you have the ability to put it in the left side of an assignment to assign another value. So, I see two reasons for it. (1) Avoid an unnecessary copy. (2) Default behaviour of assignment in C++, you can do. a = (b = c) or. (a = b) = c. The first form is OK even with returning the value.

  21. c++

    as far as I know the Assignment Operator must be overloaded when I want to copy a Object and its values to another Object after initialization (Same of CopyConstructor, but when its initialized). Object a; Object b; // do something with a. b = a; //for this line, the Assignment Parameter must be overloaded (nearly never do such things) Object c ...

  22. Different Ways of Operator Overloading in C++

    Explanation: Here, d1 calls the operator function of its class object and takes d2 as a parameter, by which the operator function returns the object and the result will reflect in the d3 object. It is generally preferred to overload binary operator as global function. It is because in global function, both the object or the value that can be converted to the object can be used as either left ...

  23. c++11

    in this class we have a std::thread that runs in the constructor and has access to the _id of this class. how can we implement copy and move constructor and assignment for this class? class MyClass {

  24. c++

    Using this approach, C::operator=() would be implemented to call A::operator=() and to allocate/copy/release c. Furthermore, the destructors of B and C should generally not release A s members. When B and C are destructed, A s constructor is called implicitly (so your approach will result in A::name being destroyed twice, which results in ...

  25. should we delete move constructor and assignment in this code?

    in this code On_heap is a wrapper that manages an object on heap. is deleting move constructor and assignment here are mandatory?. template<typename T> struct On_heap { On_heap() :p(new T) { } // allocate ˜On_heap() { delete p; } // deallocate T& operator∗() { return ∗p; } T∗ operator−>() { return p; } On_heap(const On_heap&) = delete; // prevent copying On_heap operator=(const On ...