Copy assignment operator

A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . A type with a public copy assignment operator is CopyAssignable .

[ edit ] Syntax

[ edit ] explanation.

  • Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
  • Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used
  • Forcing a copy assignment operator to be generated by the compiler
  • Avoiding implicit copy assignment

The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.

[ edit ] Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &

Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)

A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default .

Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.

[ edit ] Deleted implicitly-declared copy assignment operator

The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true:

  • T has a non-static data member that is const
  • T has a non-static data member of a reference type.
  • T has a non-static data member that cannot be copy-assigned (has deleted, inaccessible, or ambiguous copy assignment operator)
  • T has direct or virtual base class that cannot be copy-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
  • T has a user-declared move constructor
  • T has a user-declared move assignment operator

[ edit ] Trivial copy assignment operator

The implicitly-declared copy assignment operator for class T is trivial if all of the following is true:

  • T has no virtual member functions
  • T has no virtual base classes
  • The copy assignment operator selected for every direct base of T is trivial
  • The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial

A trivial copy assignment operator makes a copy of the object representation as if by std:: memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.

[ edit ] Implicitly-defined copy assignment operator

If the implicitly-declared copy assignment operator is not deleted or trivial, it is defined (that is, a function body is generated and compiled) by the compiler. For union types, the implicitly-defined copy assignment copies the object representation (as by std:: memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using, using built-in assignment for the scalars and copy assignment operator for class types.

The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.

[ edit ] Notes

If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std:: move ), and selects the copy assignment if the argument is lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.

[ edit ] Copy and swap

Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:

T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg     swap ( arg ) ;     // resources exchanged between *this and arg     return * this ; }   // destructor is called to release the resources formerly held by *this

For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move).

[ edit ] Example

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

cppreference.com

Copy assignment operator.

A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.

[ edit ] Syntax

[ edit ] explanation.

  • Typical declaration of a copy assignment operator when copy-and-swap idiom can be used.
  • Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance).
  • Forcing a copy assignment operator to be generated by the compiler.
  • Avoiding implicit copy assignment.

The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.

[ edit ] Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B & or const volatile B & ;
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M & or const volatile M & .

Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.)

A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)

The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) exception specification (since C++17)

Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.

[ edit ] Deleted implicitly-declared copy assignment operator

A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a user-declared move constructor;
  • T has a user-declared move assignment operator.

Otherwise, it is defined as defaulted.

A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a non-static data member of non-class type (or array thereof) that is const ;
  • T has a non-static data member of a reference type;
  • T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
  • T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.

[ edit ] Trivial copy assignment operator

The copy assignment operator for class T is trivial if all of the following is true:

  • it is not user-provided (meaning, it is implicitly-defined or defaulted) , , and if it is defaulted, its signature is the same as implicitly-defined (until C++14) ;
  • T has no virtual member functions;
  • T has no virtual base classes;
  • the copy assignment operator selected for every direct base of T is trivial;
  • the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial;

A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.

[ edit ] Implicitly-defined copy assignment operator

If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.

The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.

[ edit ] Notes

If 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 lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.

It is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined copy assignment operator (same applies to move assignment ).

See assignment operator overloading for additional detail on the expected behavior of a user-defined copy-assignment operator.

[ edit ] Example

[ edit ] defect reports.

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • Pages with unreviewed CWG DR marker
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 9 January 2019, at 07:16.
  • This page has been accessed 570,566 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers
  • 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.12 — Overloading the assignment operator

The copy assignment operator (operator=) is used to copy values from one object to another already existing object .

Related content

As of C++11, C++ also supports “Move assignment”. We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

Copy assignment vs Copy constructor

The purpose of the copy constructor and the copy assignment operator are almost equivalent -- both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.

The difference between the copy constructor and the copy assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:

  • If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value).
  • If a new object does not have to be created before the copying can occur, the assignment operator is used.

Overloading the assignment operator

Overloading the copy assignment operator (operator=) is fairly straightforward, with one specific caveat that we’ll get to. The copy assignment operator must be overloaded as a member function.

This prints:

This should all be pretty straightforward by now. Our overloaded operator= returns *this, so that we can chain multiple assignments together:

Issues due to self-assignment

Here’s where things start to get a little more interesting. C++ allows self-assignment:

This will call f1.operator=(f1), and under the simplistic implementation above, all of the members will be assigned to themselves. In this particular example, the self-assignment causes each member to be assigned to itself, which has no overall impact, other than wasting time. In most cases, a self-assignment doesn’t need to do anything at all!

However, in cases where an assignment operator needs to dynamically assign memory, self-assignment can actually be dangerous:

First, run the program as it is. You’ll see that the program prints “Alex” as it should.

Now run the following program:

You’ll probably get garbage output. What happened?

Consider what happens in the overloaded operator= when the implicit object AND the passed in parameter (str) are both variable alex. In this case, m_data is the same as str.m_data. The first thing that happens is that the function checks to see if the implicit object already has a string. If so, it needs to delete it, so we don’t end up with a memory leak. In this case, m_data is allocated, so the function deletes m_data. But because str is the same as *this, the string that we wanted to copy has been deleted and m_data (and str.m_data) are dangling.

Later on, we allocate new memory to m_data (and str.m_data). So when we subsequently copy the data from str.m_data into m_data, we’re copying garbage, because str.m_data was never initialized.

Detecting and handling self-assignment

Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:

By checking if the address of our implicit object is the same as the address of the object being passed in as a parameter, we can have our assignment operator just return immediately without doing any other work.

Because this is just a pointer comparison, it should be fast, and does not require operator== to be overloaded.

When not to handle self-assignment

Typically the self-assignment check is skipped for copy constructors. Because the object being copy constructed is newly created, the only case where the newly created object can be equal to the object being copied is when you try to initialize a newly defined object with itself:

In such cases, your compiler should warn you that c is an uninitialized variable.

Second, the self-assignment check may be omitted in classes that can naturally handle self-assignment. Consider this Fraction class assignment operator that has a self-assignment guard:

If the self-assignment guard did not exist, this function would still operate correctly during a self-assignment (because all of the operations done by the function can handle self-assignment properly).

Because self-assignment is a rare event, some prominent C++ gurus recommend omitting the self-assignment guard even in classes that would benefit from it. We do not recommend this, as we believe it’s a better practice to code defensively and then selectively optimize later.

The copy and swap idiom

A better way to handle self-assignment issues is via what’s called the copy and swap idiom. There’s a great writeup of how this idiom works on Stack Overflow .

The implicit copy assignment operator

Unlike other operators, the compiler will provide an implicit public copy assignment operator for your class if you do not provide a user-defined one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).

Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete keyword:

Note that if your class has const members, the compiler will instead define the implicit operator= as deleted. This is because const members can’t be assigned, so the compiler will assume your class should not be assignable.

If you want a class with const members to be assignable (for all members that aren’t const), you will need to explicitly overload operator= and manually assign each non-const member.

guest

Copy assignment operator

A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . A type with a public copy assignment operator is CopyAssignable .

[ edit ] Syntax

[ edit ] explanation.

  • Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
  • Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used
  • Forcing a copy assignment operator to be generated by the compiler
  • Avoiding implicit copy assignment

The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.

[ edit ] Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &

Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)

A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)

Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.

[ edit ] Deleted implicitly-declared copy assignment operator

The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true:

  • T has a non-static data member that is const
  • T has a non-static data member of a reference type.
  • T has a non-static data member that cannot be copy-assigned (has deleted, inaccessible, or ambiguous copy assignment operator)
  • T has direct or virtual base class that cannot be copy-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
  • T has a user-declared move constructor
  • T has a user-declared move assignment operator

[ edit ] Trivial copy assignment operator

The copy assignment operator for class T is trivial if all of the following is true:

  • The operator is not user-provided (meaning, it is implicitly-defined or defaulted), and if it is defaulted, its signature is the same as implicitly-defined
  • T has no virtual member functions
  • T has no virtual base classes
  • The copy assignment operator selected for every direct base of T is trivial
  • The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial

A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.

[ edit ] Implicitly-defined copy assignment operator

If the implicitly-declared copy assignment operator is not deleted or trivial, it is defined (that is, a function body is generated and compiled) by the compiler. For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using, using built-in assignment for the scalars and copy assignment operator for class types.

The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.

[ edit ] Notes

If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std::move ), and selects the copy assignment if the argument is lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.

[ edit ] Copy and swap

Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:

T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg     swap ( arg ) ;     // resources exchanged between *this and arg     return * this ; }   // destructor is called to release the resources formerly held by *this

For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move).

[ edit ] Example

CS 1124 — Object Oriented Programming

Copy control / big 3, copy constructor, assignment operator.

  • Inheritance

What are the "Big 3"?

The Big 3 refers to the destructor, the assignment operator and the copy constructor.

Why do we care?

Most of the time you don't. At least you haven't so far. But sometimes you need to. Suppose we have a simple class such as the following:

class SimpleClass { public: SimpleClass() { p = new int(17); } private: int* p; };

Now suppose we create an instance of SimpleClass in a function:

void aFunction() { SimpleClass simp; }

What happens when we call aFunction? More importantly, what happens when it finishes? The variable simp goes "out of scope". What happens to the the memory on the heap that simp.p was pointing at? It has become garbage. We now have a memory leak.

Solution? Write a destructor. But after you write the destructor, it will turn out that you want to write a copy constructor and an assignment operator, too. These three functions tend to go together - if you need one, you likely need the other two.

The destructor is pretty simple. It's job is to free up whatever resources need to be freed up when an object is about to be "destroyed". For us, the "resources" just refer to items or arrays that were allocated on the heap. If the object being destroyed is responsible for the memory on the heap, then it should have a destructor to free it up.

How do you write a destructor? First, what's its name? The destructor's name is the same as the name of the class, execept it starts with one extra character, know as "tilde" (rhymes with "Hilda").

Is there anything else special about the function? Glad you asked. Like the constructor(s), it does not have a return type. At all. Unlike the constructors, there is only one destructor. You can't overload it based on passing different parameters, because you don't ever pass parameters to a destructor.

In fact, you don't call the destructor. The "system" does.

So, here's a suitable destructor for our simple class.

~SimpleClass() { delete p; }

That's it. Free up the memory that was allocated for this object.

What does a constructor do? Initializes the member variables of an object when it is created. Sometimes constructors have parameters so that we can pass arguments to tell the constructor how to initialize the new object.

When the argument is another object of the same type, then we call the constructor a copy constructor. This is a very important constructor. It is called a lot. Here are four somewhat different times that the copy constructor is used:

  • SomeClass a; SomeClass b(a);
  • SomeClass a; SomeClass b = a;
  • void someFunc(SomeClass passedByValue) {}
  • SomeClass anotherFunc () { SomeClass returnedByValue; return returnedByValue; }

Items 1 and 2 above are both creating an object and initializing based on another object of the same type. In both cases , it is the copy constructor that is called.

Item 3 shows a function with a parameter that is passed by value. Passing by value uses the copy constructor to initialize the parameter.

Item 4 shows a function with a value that is returned by value. Returning by value uses the copy constructor to return a copy of the value that is being returned. (That all looks cyclical, but it actually says the right thing.)

Here's a suitable copy constructor for our simple class:

SimpleClass(const SimpleClass& rhs) { p = new int; // Allocate *p = *rhs.p; // Initialize (well, actually "set"). }

The constructor is allocating space on the heap, and initializing/setting that space to hold a copy of the value in the original. (There's gotta be a simpler way to say these things.).

Now for the last of the Big 3. But it's the biggest.

Responsibilities

The assignment operator has more responsibility than the copy constructor. Why?

The copy constructor is only initializing an object and doesn't have to worry about any information or resources that the object already has.

The assignment operator, on the other hand, is changing an object. It has to, possibly:

  • get rid of things the object already has
  • replace them with new things
  • copy over the values from the object on the "right-hand side" to the "left-hand side".

Step one is what the destructor does. Steps two and three together are what the copy constructor does. Sure it would be nice if we could just "call" those two functions - but we can't. However, it sure makes this function easier, knowing that it just consists of the same work we would have done for the other two.

In addition the assignment operator has to

  • return the right thing
  • check for self-assignment.

Member or non-member?

Member. The language doesn't give us a choice.

Return Type and Value

The assignment operator has a return type. (Neither the destructor nor the copy constructor did, so we didn't have to worry about them.) What should it be? Void? NOOOOO!!!! (No matter what you may read in "some" books.)

C++ programmers expect to be able to write things like:

That means the same as the parenthesized:

x = ( y = z ) ;

Guess what would happen if the value of the expression y = z was void. That line up there could not compile! That's why it has to have a value. What value? The same as what's in y after the assignment in parentheses.

That tells us that the type could be SomeClass. But should we return it by value or by reference? In other words, should the type be SomeClass or SomeClass&. The answer is SomeClass&. I'm not going to clutter this page with the reason. You can look at the gory details if you like. Otherwise, just remember to do it the right way.

Self-Assignment

What if a programmer writes:

What would the code we've outlined above do? The first thing we've said we should do is "get rid of the things the object already has". Hm, in our example with SomeClass, that means get rid (i.e. delete) the int on the heap. Well, that would be bit of a disaster. We could possibly arrange things so that we didn't end up destroying all our information, but we would still be doing a lot of unneccessary work.

We shouldn't be doing much of anything, other than recognizing that this is a simple no-brainer and returning x as the value of the expression.

How do we check for self-assignment? We need to know if the current object, since we said this is a member function, is the same object as the right-hand side. How can we check if two objects are exactly the same object? Check if their addresses are the same! What is the current object's address? this .

SimpleClass& operator= (const SimpleClass& rhs) { if (this != &rhs) { // Free up resources (as needed) delete p; // Allocate new resources (as needed) p = new int; // Copy over all data *p = *rhs.p; } return *this; }

Inheritance?

If derived does not do copy control.

class Base { public: Base() { cerr
int main() { cerr
Derived der: Base() Derived() main finished. ~Base()
  • We created a Derived object. As we already knew, in its constructor's initialization list it calls the Base constructor. That's why the first thing we see is Base() and after that Derived() .
  • The Derived object gets "destroyed" when its scope, main, is finished. Then, even though we didn't write any code to call it, the Base destructor gets called, resulting in the output ~Base()

Derived Destructor

Ok, so what's next? Let's start with the easiest of the Big 3, the destructor. We will add a destructor to Derived and observe what changes in the output. I won't repeat the Base class as it is not changing (for now).

class Derived : public Base { public: Derived() { cerr
Derived der: Base() Derived() main finished. ~Derived() ~Base()

What happened this time? Simple, when the Derived object was being destroyed, its destructor was called, resulting in the output ~Derived() . The Derived destructor, when it was done, automatically called the Base class destructor. We didn't have to do a thing!

Derived Copy Constructor

Derived der; Base() Derived() Derived der2(der); Base() Derived(const Derived&) main finished. ~Derived() ~Base() ~Derived() ~Base()

How should a Derived object get copied? Same idea here as when we asked how a Derived object should get initialized back when we started talking about inheritance. Always take care of the Base portion first. Idea is that we want a "firm foundation" to build the Derived portion on top of.

Derived der; Base() Derived() Derived der2(der); Base(const Base&) Derived(const Derived&) main finished. ~Derived() ~Base() ~Derived() ~Base()

The only change is that now we get the correct consturctor for Base being called when we make a copy of our Derived object.

Derived Assignment Operator

One more of the Big 3 to go, the assignment operator. As we did with the copy constructor, first we will write our Derived assignment operator the same way we did the one in the Base class and provide a test program.

class Derived : public Base { public: Derived() { cerr Derived& operator= (const Derived& rhs) { cerr }; int main() { cerr cerr cerr
Derived der; Base() Derived() Derived der2; Base() Derived() der = der2; operator=(const Derived&) main finished. ~Derived() ~Base() ~Derived() ~Base()
class Derived : public Base { public: Derived() { cerr Base::operator=(rhs); return *this; } };
Derived der; Base() Derived() Derived der2; Base() Derived() der = der2; operator=(const Derived&) operator=(const Base&) main finished. ~Derived() ~Base() ~Derived() ~Base()

We wee the same call to Derived's assignment operator and an additional call to Base's assignment operator.

One More Thing

We have one more job to take care of. Consider the following test code, using our current class definitions:

Derived* p = new Derived(); Base() Derived() delete p; ~Derived() ~Base() main finished.

But what happens if we change our test program just slightly? Instead of storing the address of our Derived object in a Derived pointer variable we will use a Base pointer variable.

int main() { cerr cerr
Base* p = new Derived(); Base() Derived() delete p; ~Base() main finished.
class Base { public: Base() { cerr virtual ~Base() { cerr Base& operator=(const Base& rhs) { cerr
Base* p = new Derived(); Base() Derived() delete p; ~Derived() ~Base() main finished.
  • destructor: no need to do anything
  • copy constructor: in the initialization list, call the Base copy contructor
  • assingment operator: before doing anything else, explicitly call the Base assignment operator.
  • destructor: mark it virtual.

Maintained by John Sterling ( [email protected] ). Last updated Jan. 6, 2013

Assignment operators

Assignment operators modify the value of the object.

Explanation

copy assignment operator replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is a special member function, described in copy assignment operator .

move assignment operator replaces the contents of the object a with the contents of b , avoiding copying if possible ( b may be modified). For class types, this is a special member function, described in move assignment operator . (since C++11)

For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment .

compound assignment operators replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b .

Builtin direct assignment

The direct assignment expressions have the form

For the built-in operator, lhs may have any non-const scalar type and rhs must be implicitly convertible to the type of lhs .

The direct assignment operator expects a modifiable lvalue as its left operand and an rvalue expression or a braced-init-list (since C++11) as its right operand, and returns an lvalue identifying the left operand after modification.

For non-class types, the right operand is first implicitly converted to the cv-unqualified type of the left operand, and then its value is copied into the object identified by left operand.

When the left operand has reference type, the assignment operator modifies the referred-to object.

If the left and the right operands identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same)

In overload resolution against user-defined operators , for every type T , the following function signatures participate in overload resolution:

For every enumeration or pointer to member type T , optionally volatile-qualified, the following function signature participates in overload resolution:

For every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signature participates in overload resolution:

Builtin compound assignment

The compound assignment expressions have the form

The behavior of every builtin compound-assignment expression E1 op = E2 (where E1 is a modifiable lvalue expression and E2 is an rvalue expression or a braced-init-list (since C++11) ) is exactly the same as the behavior of the expression E1 = E1 op E2 , except that the expression E1 is evaluated only once and that it behaves as a single operation with respect to indeterminately-sequenced function calls (e.g. in f ( a + = b, g ( ) ) , the += is either not started at all or is completed as seen from inside g ( ) ).

In overload resolution against user-defined operators , for every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signatures participate in overload resolution:

For every pair I1 and I2, where I1 is an integral type (optionally volatile-qualified) and I2 is a promoted integral type, the following function signatures participate in overload resolution:

For every optionally cv-qualified object type T , the following function signatures participate in overload resolution:

Operator precedence

Operator overloading

Copy assignment operators (C++ only)

The copy assignment operator lets you create a new object from an existing one by initialization. A copy assignment operator of a class A is a nonstatic non-template member function that has one of the following forms:

  • A::operator=(A)
  • A::operator=(A&)
  • A::operator=(const A&)
  • A::operator=(volatile A&)
  • A::operator=(const volatile A&)

If you do not declare a copy assignment operator for a class A , the compiler will implicitly declare one for you that is inline public.

The assignment x = y calls the implicitly defined copy assignment operator of B , which calls the user-defined copy assignment operator A::operator=(const A&) . The assignment w = z calls the user-defined operator A::operator=(A&) . The compiler will not allow the assignment i = j because an operator C::operator=(const C&) has not been defined.

The implicitly declared copy assignment operator of a class A will have the form A& A::operator=(const A&) if the following statements are true:

  • A direct or virtual base B of class A has a copy assignment operator whose parameter is of type const B& , const volatile B& , or B .
  • A non-static class type data member of type X that belongs to class A has a copy constructor whose parameter is of type const X& , const volatile X& , or X .

If the above are not true for a class A , the compiler will implicitly declare a copy assignment operator with the form A& A::operator=(A&) .

The implicitly declared copy assignment operator returns an lvalue reference to the operator's argument.

The copy assignment operator of a derived class hides the copy assignment operator of its base class.

  • Class A has a nonstatic data member of a const type or a reference type
  • Class A has a nonstatic data member of a type which has an inaccessible copy assignment operator
  • Class A is derived from a base class with an inaccessible copy assignment operator.

An implicitly defined copy assignment operator of a class A will first assign the direct base classes of A in the order that they appear in the definition of A . Next, the implicitly defined copy assignment operator will assign the nonstatic data members of A in the order of their declaration in the definition of A .

  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Copy Constructor vs Assignment Operator in C++

  • How to Create Custom Assignment Operator in C++?
  • Assignment Operators In C++
  • Why copy constructor argument should be const in C++?
  • Advanced C++ | Virtual Copy Constructor
  • Move Assignment Operator in C++ 11
  • Self assignment check in assignment operator
  • Is assignment operator inherited?
  • Copy Constructor in C++
  • How to Implement Move Assignment Operator in C++?
  • Default Assignment Operator and References in C++
  • Can a constructor be private in C++ ?
  • When is a Copy Constructor Called in C++?
  • C++ Assignment Operator Overloading
  • std::move in Utility in C++ | Move Semantics, Move Constructors and Move Assignment Operators
  • C++ Interview questions based on constructors/ Destructors.
  • Problem with Single Argument Constructor in C++ and How to solve it
  • Conversion Operators in C++
  • Constructor Overloading in C++
  • When Should We Write Our Own Copy Constructor in C++?
  • How to Handle Incorrect Values in a Constructor?
  • Assignment Operators in C
  • Copy Constructor in Python
  • Copy Constructor in Java
  • Constructors in Objective-C
  • C# | Copy Constructor
  • Assignment Operators in Programming
  • Class Constructor Methods in MATLAB
  • Solidity - Assignment Operators
  • Output of C++ programs | Set 26 (Constructors)

Copy constructor and Assignment operator are similar as they are both used to initialize one object using another object. But, there are some basic differences between them:

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 , same as Test t3(t1);

Must Read: When is a Copy Constructor Called in C++?

Please Login to comment...

Similar reads.

advertisewithusBannerImg

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

IMAGES

  1. Why We Must Return Reference In Copy Assignment Operator?

    copy assignment operator return type

  2. C++: Constructor, Copy Constructor and Assignment operator

    copy assignment operator return type

  3. Programming example: Copy assignment operator

    copy assignment operator return type

  4. C++ : Why must the copy assignment operator return a reference/const

    copy assignment operator return type

  5. C/C++ 中的赋值运算符

    copy assignment operator return type

  6. Difference between copy constructor and assignment operator in c++

    copy assignment operator return type

VIDEO

  1. #20. Assignment Operators in Java

  2. Java Programming # 44

  3. History copy / assignment first page idea

  4. Day 6

  5. Day 99:Fastest way to COPY assignment from Mobile 📲 #hack #youtubeshorts #shortsfeed #viral #shorts

  6. C++ Dersleri 23

COMMENTS

  1. 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 ...

  2. Why must the copy assignment operator return a reference/const

    C++98 §23.1/4: " In Table 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly const) T. Returning a copy by value would still support assignment chaining like a = b = c = 42;, because the assignment operator is right-associative, i.e. this is parsed as a = (b = (c = 42));.

  3. Copy assignment operator

    The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially copy-assignable.

  4. 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.

  5. Copy assignment operator

    A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T, T &, const T &, volatile T &, or const volatile T &. For a type to be CopyAssignable, it must have a public copy assignment operator.

  6. Assignment operator (C++)

    The copy assignment operator, often just called the "assignment operator", is a special case of assignment operator where the source (right-hand side) and destination ... The language permits an overloaded assignment operator to have an arbitrary return type (including void). However, the operator is usually defined to return a reference to the ...

  7. What is the return type of the built-in assignment operator?

    The return type is important for chaining operations. Consider the following construction: a = b = c;. This should be equal to a = (b = c), i.e. c should be assigned into b and b into a. Rewrite this as a.operator=(b.operator=(c)). In order for the assignment into a to work correctly the return type of b.operator=(c) must be reference to the ...

  8. Everything You Need To Know About The Copy Assignment Operator In C++

    The Copy Assignment Operator in a class is a non-template non-static member function that is declared with the operator=. When you create a class or a type that is copy assignable (that you can copy with the = operator symbol), it must have a public copy assignment operator. Here is a simple syntax for the typical declaration of a copy ...

  9. Copy constructors, assignment operators,

    While the return type may not be too important, choice of the parameter type is critical. (2), (5), and (8) pass the right-hand side by non-const reference, ... in either T's copy constructor or assignment operator throwing, you are politely required to provide a swap() overload for your type that does not throw. [Since swap() cannot return ...

  10. 21.12

    21.12 — Overloading the assignment operator. 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 .

  11. Copy assignment operator

    Implicitly-declared copy assignment operator. If no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T:: operator = (const T &) if all of the following is ...

  12. CS 1124

    In addition the assignment operator has to . return the right thing ; check for self-assignment. Member or non-member? Member. The language doesn't give us a choice. Return Type and Value. The assignment operator has a return type. (Neither the destructor nor the copy constructor did, so we didn't have to worry about them.) What should it be? Void?

  13. Assignment operators

    Assignment operators. Assignment operators modify the value of the object. All built-in assignment operators return *this, and most user-defined overloads also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type ...

  14. Has anyone found the need to declare the return parameter of a copy

    An answer that mirrors one from Overloading assignment operator in C++:. Returning a const& will still allow assignment chaining:. a = b = c; But will disallow some of the more unusual uses: (a = b) = c; Note that this makes the assignment operator have semantics similar to what it has in C, where the value returned by the = operator is not an lvalue. In C++, the standard changed it so the ...

  15. Copy assignment operators (C++ only)

    Copy assignment operators (C++ only) The copy assignment operator lets you create a new object from an existing one by initialization. A copy assignment operator of a class A is a nonstatic non-template member function that has one of the following forms: If you do not declare a copy assignment operator for a class A, the compiler will ...

  16. Return type of assignment operator in C++

    The return type doesn't have to be A&; the standard only says:. A user-declared copy assignment operator X :: operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X&, or const volatile X&.. We do that by convention. The oft-cited argument is that you can then "chain" assignments (a = b = c), though to be honest that's ...

  17. Copy Constructor vs Assignment Operator in C++

    But, there are some basic differences between them: Copy constructor. Assignment operator. It is called when a new object is created from an existing object, as a copy of the existing object. This operator is called when an already initialized object is assigned a new value from another existing object. It creates a separate memory block for ...

  18. C++ Move Assignment Operator Return Type

    Normally the return type of an assignment operator is Vector&, but const Vector& is acceptable if you don't want people making funky assignment chains (((v1 = v2) = v3) = v4). Move assignment and copy assignment are both "assignment". It would be unexpected for one assignment operator to have a different return type than the other, so whichever ...