avatar

The copy and swap idiom in C++

Last year, as the usage of our services grew sometimes by 20 times, we had to spend significant efforts on optimizing our application. Although these are C++-backed services, our focus was not on optimizing the code. We had to change certain things, but removing not needed database connections I wouldn’t call performance optimization. It was rather fixing a bug.

In my experience, while performance optimization is an important thing, often the bottleneck is about latency. It’s either about the network or the database.

Checking some of our metrics, we saw some frontend queueing every hour.

Long story short, it was about a materialized view . We introduced it for better performance, but seemingly it didn’t help enough.

What could we do?

The view was refreshed every hour. A refresh meant that the view was dropped, then in a few seconds, a new one was built. The few seconds of downtime were enough to build up a queue.

We found a setting to have an out-of-place refresh. With that, the new view was built up while the old one was still in use. Then once ready, Oracle started to use the new view and drop the old.

The queueing vanished.

We traded some space for time.

The idea is not exclusive to databases obviously. In C++, there is a similar concept, an idiom, called copy-and-swap .

The motivations

But are the motivations the same?

Not exactly.

Even though I can imagine a situation where there is a global variable that can be used by different threads and it’s crucial limiting the time spent updating that variable.

There is something more important.

It’s about the safety of copy assignments. What is a copy assignment about? You create a new object and assign it to an already existing variable. The object that was held by the existing variable gets destroyed.

So there is construction and destruction. The first might fail, but destruction must not.

Is that really the case in practice?

Not necessarily.

What often happens is that the assignment is performed from member to member.

The problem is that what if the copy assignment fails? Here we deal with simple POD members, but it could easily be something more complex. Something more error-prone. If the copy fails, if constructing any of those members fails, our object which we wanted to assign to remains in an inconsistent state.

That is basic exception safety at best. Even if all the values remain valid, they might differ from the original.

The C++ standard library provides several levels of exception safety (in decreasing order of safety) : 1) No-throw guarantee, also known as failure transparency: Operations are guaranteed to succeed and satisfy all requirements even in exceptional situations. If an exception occurs, it will be handled internally and not observed by clients. 2) Strong exception safety, also known as commit or rollback semantics: Operations can fail, but failed operations are guaranteed to have no side effects, leaving the original values intact.[9] Basic exception safety: Partial execution of failed operations can result in side effects, but all invariants are preserved. Any stored data will contain valid values which may differ from the original values. Resource leaks (including memory leaks) are commonly ruled out by an invariant stating that all resources are accounted for and managed. 3) No exception safety: No guarantees are made.

If we want strong exception safety, the copy-and-swap idiom will help us achieve that.

The building blocks

The constructions might fail, but destruction must not. Therefore, first, we should create a new object on its own and then swap it with the old one. If the construction fails, the original object is not modified at all. We are on the safe side. Then we should switch the handles and we know that the destruction of the temporary object with the old data will not fail.

Let’s see it in practice.

We need three things to implement the copy and swap idiom. We need a copy constructor and a destructor which are not very big requirements and we also need a swap function. The swap function has to be able to swap two objects of the same class, do it, member, by member, and without throwing any exception.

We want our copy assignment operator to look like this:

The swap function should swap, or in other words, exchange the content of two objects, member by member. For that, we cannot use std::swap , because that needs both a copy-assignment and a copy-constructor, something we try to build up ourselves. Here is what we can do instead.

There are probably three things to note here. 1) We call swap member-by-member. 2) We call swap unqualified, while we also use using std::swap . By importing std::swap to our namespace, the compiler can decide whether a custom swap or the standard one will be called. 3) We made swap a friend function. Find out here about the reasons!

At this point, whether you need to explicitly write the copy constructor and the destructor depends on what kind of data your class manages. Have a look at the “Hinnant table”! As we wrote a constructor and a copy assignment, the copy constructor and the destructor are defaulted. But who can memorize the table?

The Hinnant table

It’s better to follow the rule of five and simply write all the special functions if we wrote one. Though we can default the missing ones. So let’s have the solution right here.

What about pointer members?

If our class has a pointer member, the copy constructor has to be properly implemented to perform a deep copy and of course, the destructor also must be correct so that we can avoid having leaks. At the same time, the assignment operator doesn’t have to be changed, swapping is still correct.

Let’s have a small example here, I simply changed the int members to unique_ptr s.

Any drawbacks?

By implementing the copy-and-swap idiom we get less code repetition as in the copy assignment we call the copy constructor. We also get strong exception safety. Is there a catch?

You might get a performance hit. After all, we have to make an extra allocation in the copy assignment where we create the temporary. This might or might not be relevant depending on your case. The more complex your class is and the more you use it in a container, the more significant the problem gets.

In simpler cases, the differences might even be optimized away, as happened with the above classes. You cannot simply assume. Before you commit to a decision, measure, measure, and measure!

Copy and swap is an idiom in C++ that brings strong exception safety for copying objects. It also removes a bit of code duplication, though it might seem a bit of overkill sometimes.

Keep in mind that the extra safety might cost you a bit of performance. Nothing is ever black and white, there are tradeoffs to be made.

I’d go with the extra safety by default, otherwise measure, measure and measure so that you can make an informed decision.

Connect deeper

If you liked this article, please

Further Reading

C++ software design by klaus iglberger.

The first time I - virtually - met Klaus was at C++ On Sea, I think in 2020. He held a workshop about modern software design which I managed to partially attend. He spoke in a slow and friendly man...

Hands-On Design Patterns with C++ by Fedor Pikus

In Hands-On Design Patterns with C++, the author Fedor Pikus shares the most common design patterns used in modern C++. In fact, not only design patterns but also some best practices and idioms. He...

The decorator pattern and binary sizes

In one of the previous articles on binary sizes, we discussed how making a class polymorphic by using the virtual keyword affects the binary size. Turning a function into virtual has a substantial ...

Price's law and 3 things to do if you're underpaid

3 ways to stay motivated when you are leaving your job

Comments powered by Disqus .

Trending Tags

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

C++ Patterns

Copy-and-swap.

This pattern is licensed under the CC0 Public Domain Dedication .

Implement the assignment operator with strong exception safety.

Description

The copy-and-swap idiom identifies that we can implement a classes copy/move assignment operators in terms of its copy/move constructor and achieve strong exception safety.

The class foo , on lines 7–45 , has an implementation similar to the rule of five , yet its copy and move assignment operators have been replaced with a single assignment operator on lines 24–29 . This assignment operator takes its argument by value, making use of the existing copy and move constructor implementations.

To implement the assignment operator, we simply need to swap the contents of *this and the argument, other . When other goes out of scope at the end of the function, it will destroy any resources that were originally associated with the current object.

To achieve this, we define a swap function for our class on lines 36–41 , which itself calls swap on the class’s members ( line 40 ). We use a using-declaration on line 38 to allow swap to be found via argument-dependent lookup before using std::swap — this is not strictly necessary in our case, because we are only swapping a pointer, but is good practice in general. Our assignment operator then simply swaps *this with other on line 26 .

The copy-and-swap idiom has inherent strong exception safety because all allocations (if any) occur when copying into the other argument, before any changes have been made to *this . It is generally, however, less optimized than a more custom implementation of the assignment operators.

Note : We can typically avoid manual memory management and having to write the copy/move constructors, assignment operators, and destructor entirely by using the rule of zero

Contributors

Mattijs Kneppers

Last Updated

23 February 2018

Fork this pattern on GitHub

MC++ BLOG

The Copy-and-Swap Idiom

An idiom is an architectural or design pattern implementation in a concrete programming language. Applying them is idiomatic for a programming language. Today. I write about the Copy-and-Swap Idiom in C++. This idiom gives you the strong exception safety guarantee.

GeneralIdioms

Before I write about the Copy-and-Swap Idiom, I should first clarify the strong exception safety guarantee. Here are a few general thoughts about error handling:

Error Handling

When you handle an error, the following aspects should be considered:

  • Detect an error
  • Transmit information about an error to some handler code
  • Preserve the valid state of a program
  • Avoid resource leaks

You should use exceptions for error handling. In the document “ Exception-Safety in Generic Components ” David Abrahams formalized what exception-safety means.

Abrahams Guarantees

Abrahams Guarantees describe a contract that is fundamental if you think about exception safety. Here are the four levels of the contract:

  • No-throw guarantee , also known as failure transparency : Operations are guaranteed to succeed and satisfy all requirements, even in exceptional situations. If an exception occurs, it is handled internally and cannot be observed by clients.
  • Strong exception safety , also known as commit or rollback semantics : Operations can fail, but failed operations are guaranteed to have no side effects, so all data retain their original values.
  • Basic exception safety , also known as a no-leak guarantee: Partial execution of failed operations can cause side effects, but all invariants are preserved, and there are no resource leaks (including memory leaks). Any stored data contains valid values, even if they differ from what they were before the exception.
  • No exception safety : No guarantees are made.

In general, you should at least aim for the basic exception safety guarantee. This means that you don’t have resource leaks in case of an error, and your program is always in a well-defined state. If your program is not in a well-defined state after an error, there is only one option left: shut down your program.

I stated that the Copy-and-Swap Idiom provides a strong exception safety guarantee. This is a stronger guarantee such as the basic exception safety guarantee.

Modernes C++ Mentoring

Be part of my mentoring programs:

  • " Fundamentals for C++ Professionals " (open)
  • " Design Patterns and Architectural Patterns with C++ " (open)
  • " C++20: Get the Details " (open)
  • " Concurrency with Modern C++ " (starts March 2024)

Do you want to stay informed: Subscribe.

Okay, I know what copy means. Therefore, let me write about swap:

The swap function

For a type to be a regular type, it has to support a swap function. A more informal definition of regular type is a value-like type that behaves like an int . I will write about regular types in an upcoming post. According to the rules “ C.83: For value-like types, consider providing a noexcept swap function ” and “ C.85: Make swap noexcept ” of the C++ Core Guidelines, a swap function should not fail and be noexcept .

The following data type Foo has a swap function.

For convenience reasons, you should consider supporting a non-member swap function based on the already implemented swap member function.

If you do not provide a non-member swap function, then the standard library algorithms that require swapping (such as std::sort and std::rotate ) will fall back to the std::swap template, which is defined in terms of move construction and move assignment.

The C++ standard offers more than 40 overloads of std::swap . You can use the swap function as a building block for many idioms, such as copy construction or move assignment.

This brings me to the Copy-and-Swap Idiom.

Copy-And-Swap

If you use the Copy-and-Swap Idiom to implement the copy assignment and the move assignment operator, you must define your own swap — either as a member function or as a friend. I added a swap function to the class Cont and used it in the copy assignment and move assignment operator.

Both assignment operators make a temporary copy tmp of the source object (lines 1 and ) and then apply the swap function to it (lines 3 and 4). When the used swap functions are noexcept , the copy assignment operator and the move assignment operator support the strong exception safety guarantee. This means that both assignment operators guarantee that the operations call will be fully rolled back in case of an error such as the error never happened.

Operations supporting the Copy-and-Swap Idiom allow you to program in a transaction-based style. You prepare an operation (working on the copy) and publish the operation (swap the result) when it is fine. The Copy-and-Swap Idiom is a very powerful idiom that is applied pretty often.

  • Concurrent programming : You make your modification on a local object. This is, by definition, thread-safe because the data is not shared. When you are done with your change, you overwrite the shared data with your local data in a protected way.
  • Version control system : First, you check out the data and get a local copy. When you are done with your change, you commit your change and have to handle merge conflicts eventually. In case you cannot solve the merge conflict, you throw away your local change and check out once more.

When a swap function is based on copy semantics instead of move semantics, a swap function may fail because of memory exhaustion. The following implementation contradicts the C++ Core Guidelines rule “ C++94: A swap function must not fail “.This is the C++98 implementation of std::swap .

 In this case, memory exhaustion may cause a std::bad_alloc exception.

What’s Next?

Partial Function Application is a technique in which a function binds a few of its arguments and returns a function taking fewer arguments. This technique is related to a technique used in functional languages called currying.

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ – The Core Language
  • C++ – The Standard Library
  • C++ – Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++
  • Clean Code with Modern C++

Online Seminars (German)

  • Embedded Programmierung mit modernem C++   (2. Jul 2024 bis 4. Jul 2024)
  • Phone: +49 7472 917441
  • Mobil: +49 176 5506 5086
  • Mail: [email protected]
  • German Seminar Page: www.ModernesCpp.de
  • Mentoring Page: www.ModernesCpp.org

Modernes C++ Mentoring,

copy assignment operator swapping objects

Leave a Reply

Leave a reply cancel reply.

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

PythonCpp

Copy and Swap, 20 years later

It’s dangerous to go alone, back to the 90s, warrantee voids if exception happens, in conclusion, mathieu ropert.

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

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 & . 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)

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

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

[ 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). However, this approach is not always advisable due to potentially significant overhead: see assignment operator overloading for details.

[ edit ] Example

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.

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.

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.

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.

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.

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.

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.

Defect reports

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

  • 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.
  • Assignment Operators in C
  • Copy Constructor in Python
  • Copy Constructor in Java
  • Constructors in Objective-C

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, improve your coding skills with practice.

 alt=

What kind of Experience do you want to share?

IMAGES

  1. Programming example: Copy assignment operator

    copy assignment operator swapping objects

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

    copy assignment operator swapping objects

  3. Copy Constructor and Copy Assignment Operator (Lecture 26)

    copy assignment operator swapping objects

  4. Copy Constructor vs Assignment Operator,Difference between Copy Constructor and Assignment Operator

    copy assignment operator swapping objects

  5. Solved C++ Assignment Operator: Swapping ObjectsGiven a

    copy assignment operator swapping objects

  6. What is the Difference Between Copy Constructor and Assignment Operator

    copy assignment operator swapping objects

VIDEO

  1. Java Programming # 44

  2. History copy / assignment first page idea

  3. 043024 COSC 1337 C++ Class Memory Mgmt: copy assignment

  4. Lec:10 swapping two number using XOR operator or without using third variable??🤔🤔🤔🤔

  5. 043024 COSC 1337 C++ Class Memory Mgmt: Intro Copy Assignment

  6. Session 1

COMMENTS

  1. Copy assignment operator

    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.

  2. c++

    The copy-and-swap idiom is a way to do just that: It first calls a class' copy constructor to create a temporary object, then swaps its data with the temporary's, and then lets the temporary's destructor destroy the old state. Since swap() is supposed to never fail, the only part which might fail is the copy-construction.

  3. Copy-and-Swap Idiom in C++

    In the above example, the parameter to the 'operator=()' is passed by value which calls copy constructor to create a anyArrayClass object local to the 'operator=()'. Than the value of the temp object is swapped with '*this' object (LHS of assignment operator call). Advantages:

  4. The copy and swap idiom in C++

    We need three things to implement the copy and swap idiom. We need a copy constructor and a destructor which are not very big requirements and we also need a swap function. The swap function has to be able to swap two objects of the same class, do it, member, by member, and without throwing any exception. We want our copy assignment operator to ...

  5. Copy assignment operator

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

  6. Copy-and-swap

    The copy-and-swap idiom identifies that we can implement a classes copy/move assignment operators in terms of its copy/move constructor and achieve strong exception safety. The class foo, on lines 7-45, has an implementation similar to the rule of five, yet its copy and move assignment operators have been replaced with a single assignment ...

  7. The Copy-and-Swap Idiom

    Both assignment operators make a temporary copy tmp of the source object (lines 1 and ) and then apply the swap function to it (lines 3 and 4). When the used swap functions are noexcept, the copy assignment operator and the move assignment operator support the strong exception safety guarantee. This means that both assignment operators ...

  8. Copy and Swap, 20 years later · Mathieu Ropert

    Write the copy-assignment operator by making a temporary copy of the source object, then swap the copy with this. This 4th point is the most elegant and important part of the idiom. Copy-assignment is usually the trickiest one to write since it must delete existing content, insert a copy of the source objects and survive if an exception is ...

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

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

    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:. Point a, b; ... a = b; 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 ...

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

    Classes and Objects are part of object-oriented methods and typically provide features such as properties and methods. One of the great features of an object orientated language like C++ is a copy assignment operator that is used with operator= to create a new object from an existing one. In this post, we explain what a copy assignment operator is and its types in usage with some C++ examples.

  12. Is it possible to write a common function that handles both the copy

    While the copy ctor first-time initializes the object's members, the assignment operator overrides existing values. Considering this, alling operator= from the copy ctor is in fact pretty bad, because it first initializes all values to some default just to override them with the other object's values right afterwards. -

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

  14. Typical Declaration Of A Copy Assignment Operator With std::swap

    Object-Oriented Programming (OOP) is a method of mapping real-world objects and data to computer functions and data structures.Classes and Objects are part of object-oriented methods and typically provide features such as properties and methods. One of the features of an OOP tool is the copy assignment operator that is used with "operator=" to create a new object from an existing one.

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

  16. Copy and Swap Idiom. Learn about the copy and swap idiom and…

    Copy-and-swap idiom can be used to define copy assignment operator with a strong exception guarantee and reducing code duplication. It works by creating a temporary object containing copy of the ...

  17. Copy assignment operator

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

  18. More C++ Idioms/Copy-and-swap

    copy elision and copy-and-swap idiom. Strictly speaking, explicit creation of a temporary inside the assignment operator is not necessary. The parameter (right hand side) of the assignment operator can be passed-by-value to the function. The parameter itself serves as a temporary. String & operator = (String s) // the pass-by-value parameter ...

  19. Copy assignment operator

    Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance). ... 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. Implicitly-declared copy assignment operator.

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

  21. Using swap inside assignment move operator

    Implementing copy-assignment via swap is a good idea, but you missed some of the details. ... or by letting std::swap call your move assignment operator. Move assignment should NOT be implemented using swap. We already have an excellent guide to the ... In the end, what you want (assuming your member objects are designed correctly) is: class ...