• Windows Programming
  • UNIX/Linux Programming
  • General C++ Programming
  • Assignment operator implicitly deleted

  Assignment operator implicitly deleted

assignment operator deleted c

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

cppreference.com

Search

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

  • 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 30 November 2015, at 07:24.
  • This page has been accessed 110,155 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

Fluent C++

About Jonathan Boccara

Hello, my name is Jonathan Boccara, I'm your host on Fluent C++. I have been a developer for 10 years. My focus is on how to write expressive code . I wrote the book The Legacy Code Programmer's Toolbox . I'm happy to take your feedback, don't hesitate to drop a comment on a post, follow me or get in touch directly !

Jonathan Boccara's blog

Recent Posts

  • Usage First, Implementation After: A Principle of Software Development
  • Design Patterns VS Design Principles: Factory method
  • How to Store an lvalue or an rvalue in the Same Object
  • Copy-Paste Developments
  • Design Patterns VS Design Principles: Abstract Factory
  • How to Generate All the Combinations from Several Collections

assignment operator deleted c

How to Make a Copyable Object Assignable in C++

Some types in C++ have a copy constructor that doesn’t have the same semantics as their assignment operator ( operator= ).

Take references, for example. References can be copied:

But it doesn’t do the same thing as assigning to them:

With the copy, r2 points to the same thing as r1 , but with the assignment r2 still points to the same object it was pointing to before.

Or take the example of copying a lambda:

The above code compiles fine.

Now if we add the following line:

It doesn’t compile. As the compiler (clang) says:

Lambdas don’t even have an operator= to begin with (except in C++20 where they do if they don’t capture anything).

Right. But is any of this a problem?

Why we need operator=

After all, the behaviour of the references makes some sense, and why on earth would we like to assign on a lambda we’ve just created?

However, there is a case when the absence of operator= becomes a problem: when the object that doesn’t have an operator= is a member of a class. It makes it difficult for that class to have an operator= itself. For one thing, the compiler is not going to write it for you.

Even for references, the compiler won’t generate an operator= for a class if one of its members is a reference. It assumes that you’d better write it yourself to choose what to do with the reference member.

This problem came up in a project I’ve been working on, the pipes library . This library has classes that have lambdas as data members, and passes objects of those classes as output iterators of STL algorithms. And in Visual Studio, the STL in debug mode calls the operator= on output iterators in the _Recheck function. So the class that contains a lambda needs an operator= .

Haven’t you ever faced too the situation where the compiler couldn’t write the operator= you needed because of a problematic data member?

The standard has us covered for references

In C++11, and equivalently in Boost long before that, std::reference_wrapper<T>  has the same behaviour as a reference (you initialize it with a reference, and it even has a operator T& ) with one exception: it has an operator= that rebinds the reference.

This means that after calling operator= between two std::reference_wrapper s, they point to the same object:

The fact that std::reference_wrapper<T> has an operator= allows the compiler to generate an operator= for the classes that contains it. And the fact that it rebinds gives the operator= of the containing class a natural behaviour.

Why is this behaviour natural? Because it is consistent with the copy of the reference: in both case, the two reference(_wrapper)s point to the same object after the operation.

The general case

Even if the case of references is solved with std::reference_wrapper , the case of the lambda remains unsolved, along with all the types that have a copy constructor and no operator= .

Let’s design a component, inspired from std::reference_wrapper , that would add to any type an operator= which is consistent with its copy constructor.

If you have an idea on how to name this component, just leave a comment below at the bottom of the post. For the time being, let’s call it assignable .

assignable needs an operator= that relies on the copy constructor of its underlying type. Fortunately, we know how to implement that with a std::optional , like we saw in How to Implement operator= When a Data Member Is a Lambda :

But now that we’ve written the copy assignment operator, the compiler is going to refrain from generating the move constructor and the move assignment operator. It’s a shame, so let’s add them back:

Now that we’ve written all this, we might as well write the copy constructor too. The compiler would have generated it for us, but I think it looks odd to write everything except this one:

Finally, in order to hide from its users the fact that assignable contains an optional , let’s add constructors that accepts a T :

Giving access to the underlying value

Like optional , assignable wraps a type to add an extra feature, but its goal is not to mimic the interface of the underlying object. So we should give access to the underlying object of assignable . We will define a get()  member function, because  operator*  and operator->  could suggest that there is an indirection (like for pointers and iterators).

The underlying object of the  assignable happens to to be the underlying object of the optional inside of the assignable :

We don’t check for the nullity of the optional, because the interface of assignable is such that all the paths leading to those dereferencing operators guarantee that the optional has been initialized.

Which gives us food for thought: optional is not the optimal solution here. It contains a piece of information that we never use: whether the optional is null or not.

A better solution would be to create a component that does placement news like optional, but without the possibility to be null.

Lets keep this as food for thought for the moment. Maybe we’ll come back to it in a later article. Please leave a comment if you have thoughts on that.

Making the assignable callable

std::reference_wrapper has a little known feature that we explored in How to Pass a Polymorphic Object to an STL Algorithm : it has an operator() that calls its underlying reference when it’s callable.

This is all the more relevant for assignable since our motivating case was a lambda.

If we don’t implement operator() , we’d have to write code like this:

Whereas with an operator() , calling code becomes more natural, resembling the one of a lambda:

Let’s do it then!

We rely on C++14 decltype(auto) . Note that we could also implement this in C++11 the following way:

The case of assignable references

Now we have implemented an assignable<T> that works when T is a lambda.

But what if T is a reference?

It can happen in the case of a function reference. In that case, we need exactly the same features as the ones we needed with the lambda.

However, assignable<T> doesn’t even compile when T is a reference. Why? Because it uses an std::optional<T> and optional references didn’t make it in the C++ standard .

Luckily, implementing assignable for references is not difficult. In fact, it’s a problem already solved by… std::reference_wrapper !

So we need to create a specialization of assignable<T> when T is a reference. It would be great if we could just write this:

But this is not possible in C++.

Instead we have to implement a type that wraps std::reference_wrapper and relies on its behaviour:

This way, we can use assignable on reference types.

Putting it all together

In summary, here is all the code of assignable all put together:

And classes can use it as a data member this way:

For such as class, the compiler would be able to generate a operator= as long as Function has a copy constructor, which many classes–including lambdas–do.

Thanks to Eric Niebler for the inspiration, as assignable was inspired from techniques I’ve seen in range-v3 , which is my go-to model for library implementation.

If you have any piece of feedback on assignable , I’d love to hear it in a comment below!

You will also like

  • How to Pass a Polymorphic Object to an STL Algorithm
  • How to Implement operator= When a Data Member Is a Lambda
  • An Alternative Design to Iterators and Ranges, Using std::optional
  • Why Optional References Didn’t Make It In C++17
  • Pointers, References and Optional References in C++
  • Smart Output Iterators: A Symmetrical Approach to Range Adaptors

twitter

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

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

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

Move assignment operator

A move 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 && , const T && , volatile T && , or const volatile T && .

Explanation

  • Typical declaration of a move assignment operator.
  • Forcing a move assignment operator to be generated by the compiler.
  • Avoiding implicit move assignment.

The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.

Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. This is not, however, a guarantee. A move assignment is less, not more restrictively defined than ordinary assignment; where ordinary assignment must leave two copies of data at completion, move assignment is required to leave only one.

Implicitly-declared move assignment operator

If no user-defined move assignment operators are provided for a class type ( struct , class , or union ), and all of the following is true:

  • there are no user-declared copy constructors;
  • there are no user-declared move constructors;
  • there are no user-declared copy assignment operators;
  • there are no user-declared destructors;

then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator=(T&&) .

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

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

Because some assignment operator (move or copy) 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 move assignment operator

The implicitly-declared or defaulted move assignment operator for class T is defined as deleted if 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 move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);
  • T has direct or virtual base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);

Trivial move assignment operator

The move 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);
  • T has no virtual member functions;
  • T has no virtual base classes;
  • the move assignment operator selected for every direct base of T is trivial;
  • the move assignment operator selected for every non-static class type (or array of class type) member of T is trivial;

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

Implicitly-defined move assignment operator

If the implicitly-declared move 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 move assignment operator copies the object representation (as by std::memmove ).

For non-union class types ( class and struct ), the move assignment operator performs full member-wise move assignment of the object's direct bases and immediate non-static members, in their declaration order, using built-in assignment for the scalars, memberwise move-assignment for arrays, and move assignment operator for class types (called non-virtually).

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 move assignment operator (same applies to copy assignment ).

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

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

Related Articles

  • Solve Coding Problems
  • std::move_iterator in C++ 11
  • std::initializer_list in C++ 11
  • C++ 11 - <atomic> Header
  • auto_ptr in C++
  • User-Defined Data Types In C
  • std::variant in C++ 17
  • Literals In C++
  • Macros In C++
  • Assignment Operators In C++
  • Mutex in C++
  • Unique_ptr in C++
  • Address Operator & in C
  • C++ Variable Templates
  • Pass By Reference In C
  • std::shared_mutex in C++
  • vTable And vPtr in C++
  • Introduction to GUI Programming in C++
  • String Functions In C++
  • C++ Program For Sentinel Linear Search

Move Assignment Operator in C++ 11

In C++ programming, we have a feature called the move assignment operator, which was introduced in C++11. It helps us handle objects more efficiently, especially when it comes to managing resources like memory. In this article, we will discuss move assignment operators, when they are useful and called, and how to create user-defined move assignment operators.

Move Assignment Operator

The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

User-Defined Move Assignment Operator

The programmer can define the move assignment operator using the syntax given below:

As you may have noticed, the move assignment operator function uses a special && reference qualifier. It represents the r-value references (generally literals or temporary values).

Usually, it returns a reference to the object (in this case, *this) so you can chain assignments together.

The move constructor is called by the compiler when the argument is an rvalue reference which can be done by std::move() function. 

Example of Move Assignment Operator

In this program, we will create a dynamic array class and create a user-defined move assignment operator.

Explanation

The move assignment operator (operator=) is used to transfer resources from one DynamicArray object to another. It releases the current resources of the destination object, takes the resources from the source object, and leaves the source object in a valid but unspecified state.

In the main function:

  • We create two DynamicArray objects, arr1 with 5 elements and arr2 with 10 elements. We print their initial states.
  • We use the move assignment operator to transfer the resources from arr1 to arr2 by calling arr2 = std::move(arr1).
  • After the move, we print the states of both arr1 and arr2. arr1 is now in a valid but unspecified state, and arr2 contains the resources of arr1.
Note: We can also define a move constructor with a move assignment operator and reduce the code redundancy by calling the move assignment operator from the move constructor. To know about move constructor, refer to the article – Move Constructors in C++

Implicit Definition of Move Assignment Operator

The compiler also defines a default move assignment operator implicitly when the following conditions are satisfied:

  • No user-defined copy constructor is present.
  • No user-defined destructor is present.
  • No user-defined move constructor is present.

Need of Move Assignment Operator

In C++, objects can manage resources like memory. When we copy an object, it can be quite slow, especially if the object holds a lot of resources. Traditional copy operations create new copies, which can lead to unnecessary memory usage and slow down your program.

This is where move assignment operators come to the rescue. They let one object take over the resources of another, without making extra copies. This can significantly boost performance in scenarios like resizing arrays or returning objects from functions.

In contrast to the copy assignment operator, the end result of the move assignment operator will be a single copy of the source object.

Please Login to comment...

  • Geeks Premier League 2023
  • Geeks Premier League

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

IMAGES

  1. Assignment Operators in C

    assignment operator deleted c

  2. Assignment Operators in C » PREP INSTA

    assignment operator deleted c

  3. Assignment Operators in C Example

    assignment operator deleted c

  4. C++ Operators

    assignment operator deleted c

  5. Assignment Operators in C

    assignment operator deleted c

  6. Assignment Operators in C++

    assignment operator deleted c

VIDEO

  1. C programming

  2. Working with Assignment operators in C| C Tutorials for Beginners

  3. 21

  4. Storing values with assignment operator

  5. Arithmetic Operator, Arithmetic Assignment Operator, Bitwise Operator

  6. OPERATOR IN C[ASSIGNMENT,RELATIONAL ,LOGICAL]

COMMENTS

  1. C++

    13 I don't see where newPair is declared, but the error message seems like enough. Why this fails: If either element in the pair is const, the assignment operator for that element is itself deleted. You couldn't assign to a const string but that's exactly what you're asking it to do when you assign to pair<const string, T>. To simplify the example

  2. Copy assignment operator

     parameter-list-no-default  (since C++11) ) = delete; (since C++11)   operator= (parameter-list-no-default ) = default; (since C++11) the class whose copy assignment operator is being declared, the class type is given as in the descriptions below of only one parameter, which is of type T& parameter-list-no-default

  3. Assignment operator implicitly deleted

    Assignment operator implicitly deleted Mar 4, 2019 at 1:53pm rozick1 (218) Hi I just received the following error message which I'm struggling to fix: 1 2 3 4 5 6 7 8

  4. Compiler Error C2280

    The compiler now considers these to have non-trivial constructors and assignment operators, and doesn't generate default implementations. When such a class is a member of a union, or an anonymous union inside of a class, the copy and move constructors and copy and move assignment operators of the union or class are implicitly defined as deleted ...

  5. Explicitly Defaulted and Deleted Functions

    Benefits of explicitly defaulted and deleted functions. In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it doesn't declare its own. These functions are known as the special member functions, and they're what make simple user-defined types in C++ ...

  6. 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 . Syntax Explanation

  7. Move assignment operator

      parameter-list-no-default     operator= (parameter-list-no-default ) = default; the class whose move assignment operator is being declared, the class type is given as in the descriptions below of only one parameter, which is of type T&&&&&&&& parameter-list-no-default

  8. Copy assignment operator

    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)

  9. How to Make a Copyable Object Assignable in C++

    Some types in C++ have a copy constructor that doesn't have the same semantics as their assignment operator (operator=). Take references, for example. ... error: object of type '(lambda at main.cpp:6:16)' cannot be assigned because its copy assignment operator is implicitly deleted. Lambdas don't even have an operator= to begin with (except ...

  10. 21.12

    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

  11. std::variant<Types...>::operator=

    C++17 copy assignment operator doesn't participate in overload resolution if any member type is not copyable defined as deleted instead P0602R4: C++17 copy/move assignment may not be trivial even if underlying operations are trivial required to propagate triviality P0608R3: C++17 converting assignment blindly assembles an overload set,

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

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

  14. Move assignment operator

    the implicitly-declared move assignment operator would not be defined as deleted, (until C++14) then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator= (T&&). A class can have multiple move assignment operators, e.g. both T& T::operator=(const T&&) and T& T::operator ...

  15. What Is Deleted Implicitly-declared Copy Assignment Operator In C++?

    What is deleted implicitly-declared 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= ".

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

    1. Typical Declaration of A Copy Assignment Operator with Swap 2. Typical Declaration of A Copy Assignment Operator ( No Swap) 3. Forced Copy Assignment Operator 4. Avoiding Implicit Copy Assignment 5. Implicitly-declared copy assignment operator 6. Deleted implicitly declared copy assignment operator 7. Trivial copy assignment operator 8.

  17. c++

    main.cpp: In function 'int main (int, char**)': main.cpp:23:24: error: use of deleted function 'IntContainer& IntContainer::operator= (const IntContainer&)' intContainers [0] = newIntContainer; // <-- Causes compiler error: ^~~~~~~~~~~~~~~ main.cpp:2:8: note: 'IntContainer& IntContainer::operator= (const IntContainer&)' is implicitly deleted b...

  18. Move Assignment Operator in C++ 11

    The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

  19. c++

    The assignment operators use a trailing ampersand before specifying the functions that should be deleted. Removing the ampersands seems to result in the same behavior. What do the ampersands do?