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?

Additional resources

Copy assignment operator

(C++11)
(C++11)
(C++11)
General topics
statement
loop
loop (C++11)
loop
loop
statement
statement
(C++11)
Literals
(C++11)
(C++11)
expression
pointer
(C++11)
(C++11)
(C++11)

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 Implicitly-declared copy assignment operator Deleted implicitly-declared copy assignment operator Trivial copy assignment operator Implicitly-defined copy assignment operator Notes Copy and swap Example

[ edit ] Syntax

class_name class_name ( class_name ) (1) (since C++11)
class_name class_name ( const class_name ) (2) (since C++11)
class_name class_name ( const class_name ) = default; (3) (since C++11)
class_name class_name ( const class_name ) = delete; (4) (since C++11)

[ 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

(C++11)
(C++11)
(C++11)
General
Members
pointer
(C++11)
specifier
specifier
Special member functions
(C++11)
(C++11)
Inheritance
(C++11)
(C++11)

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.

Syntax Explanation Implicitly-declared copy assignment operator Deleted implicitly-declared copy assignment operator Trivial copy assignment operator Implicitly-defined copy assignment operator Notes Copy and swap Example

[ edit ] Syntax

class_name class_name ( class_name ) (1)
class_name class_name ( const class_name ) (2)
class_name class_name ( const class_name ) = default; (3) (since C++11)
class_name class_name ( const class_name ) = delete; (4) (since C++11)

[ 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
has no non-static data members of -qualified type (since C++14)

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

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

Copy constructors, assignment operators, and exception safe assignment

*

MyClass& other ); MyClass( MyClass& other ); MyClass( MyClass& other ); MyClass( MyClass& other );
MyClass* other );
MyClass { x; c; std::string s; };
MyClass& other ) : x( other.x ), c( other.c ), s( other.s ) {}
);
print_me_bad( std::string& s ) { std::cout << s << std::endl; } print_me_good( std::string& s ) { std::cout << s << std::endl; } std::string hello( ); print_me_bad( hello ); print_me_bad( std::string( ) ); print_me_bad( ); print_me_good( hello ); print_me_good( std::string( ) ); print_me_good( );
, );
=( MyClass& other ) { x = other.x; c = other.c; s = other.s; * ; }
< T > MyArray { size_t numElements; T* pElements; : size_t count() { numElements; } MyArray& =( MyArray& rhs ); };
<> MyArray<T>:: =( MyArray& rhs ) { ( != &rhs ) { [] pElements; pElements = T[ rhs.numElements ]; ( size_t i = 0; i < rhs.numElements; ++i ) pElements[ i ] = rhs.pElements[ i ]; numElements = rhs.numElements; } * ; }
<> MyArray<T>:: =( MyArray& rhs ) { MyArray tmp( rhs ); std::swap( numElements, tmp.numElements ); std::swap( pElements, tmp.pElements ); * ; }
< T > swap( T& one, T& two ) { T tmp( one ); one = two; two = tmp; }
<> MyArray<T>:: =( MyArray tmp ) { std::swap( numElements, tmp.numElements ); std::swap( pElements, tmp.pElements ); * ; }

14.14 — Introduction to the copy constructor

The copy constructor

This is illustrated in the following example:

  • C++ Classes and Objects
  • C++ Polymorphism
  • C++ Inheritance
  • C++ Abstraction
  • C++ Encapsulation
  • C++ OOPs Interview Questions
  • C++ OOPs MCQ
  • C++ Interview Questions
  • C++ Function Overloading
  • C++ Programs
  • C++ Preprocessor
  • C++ Templates

Copy Constructor in C++

A copy constructor is a type of constructor that initializes an object using another object of the same class. In simple terms, a constructor which creates an object by initializing it with an object of the same class, which has been created previously is known as a copy constructor .  

The process of initializing members of an object through a copy constructor is known as copy initialization . It is also called member-wise initialization because the copy constructor initializes one object with the existing object, both belonging to the same class on a member-by-member copy basis.

Syntax of Copy Constructor in C++

Copy constructor takes a reference to an object of the same class as an argument:

Here, the const qualifier is optional but is added so that we do not modify the obj by mistake.

Syntax of Copy Constructor with Example

Syntax of Copy Constructor

Examples of Copy Constructor in C++

Example 1: user defined copy constructor.

If the programmer does not define the copy constructor, the compiler does it for us.

Example 2: Default Copy Constructor

An implicitly defined copy constructor will copy the bases and members of an object in the same order that a constructor would initialize the bases and members of the object.

Need of User Defined Copy Constructor

If we don’t define our own copy constructor, the C++ compiler creates a default copy constructor for each class which works fine in general. However, we need to define our own copy constructor only if an object has pointers or any runtime allocation of the resource like a file handle , a network connection, etc because the default constructor does only shallow copy.

Shallow Copy means that only the pointers will be copied not the actual resources that the pointers are pointing to. This can lead to dangling pointers if the original object is deleted.

shallow-copy-concept-in-cpp

Deep copy is possible only with a user-defined copy constructor. In a user-defined copy constructor, we make sure that pointers (or references) of copied objects point to new copy of the dynamic resource allocated manually in the copy constructor using new operators.

deep-copy-concept-in-cpp

Example: Class Where a Copy Constructor is Required

Following is a complete C++ program to demonstrate the use of the Copy constructor. In the following String class, we must write a copy constructor. 

Note: Such classes also need the overloaded assignment operator. See this article for more info – C++ Assignment Operator Overloading

What would be the problem if we remove the copy constructor from the above code?

If we remove the copy constructor from the above program, we don’t get the expected output. The c hanges made to str2 reflect in str1 as well which is never expected. Also, if the str1 is destroyed, the str2’s data member s will be pointing to the deallocated memory.

When is the Copy Constructor Called?

In C++, a copy constructor may be called in the following cases: 

  • When an object of the class is returned by value.
  • When an object of the class is passed (to a function) by value as an argument.
  • When an object is constructed based on another object of the same class.
  • When the compiler generates a temporary object.

It is, however, not guaranteed that a copy constructor will be called in all these cases, because the C++ Standard allows the compiler to optimize the copy away in certain cases, one example is the return value optimization (sometimes referred to as RVO).

Refer to this article for more details – When is a Copy Constructor Called in C++?

Copy Elision

In copy elision, the compiler prevents the making of extra copies by making the use to techniques such as NRVO and RVO which results in saving space and better the program complexity (both time and space); Hence making the code more optimized.

Copy Constructor vs Assignment Operator

The main difference between Copy Constructor and Assignment Operator is that the Copy constructor makes a new memory storage every time it is called while the assignment operator does not make new memory storage.

Which of the following two statements calls the copy constructor and which one calls the assignment operator? 

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

Frequently Asked Questions in C++ Copy Constructors

Can we make the copy constructor private  .

Yes, a copy constructor can be made private. When we make a copy constructor private in a class, objects of that class become non-copyable. This is particularly useful when our class has pointers or dynamically allocated resources. In such situations, we can either write our own copy constructor like the above String example or make a private copy constructor so that users get compiler errors rather than surprises at runtime.

Why argument to a copy constructor must be passed as a reference?  

If you pass the object by value in the copy constructor, it will result in a recursive call to the copy constructor itself. This happens because passing by value involves making a copy, and making a copy involves calling the copy constructor, leading to an infinite recursion. Using a reference avoids this recursion. So, we use reference of objects to avoid infinite calls.

Why argument to a copy constructor should be const?

One reason for passing const reference is, that we should use const in C++ wherever possible so that objects are not accidentally modified. This is one good reason for passing reference as const , but there is more to it than ‘ Why argument to a copy constructor should be const?’

Related Articles:

  • Constructors in C++

Please Login to comment...

Similar reads.

  • cpp-constructor
  • How to Get a Free SSL Certificate
  • Best SSL Certificates Provider in India
  • Elon Musk's xAI releases Grok-2 AI assistant
  • What is OpenAI SearchGPT? How it works and How to Get it?
  • Full Stack Developer Roadmap [2024 Updated]

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Why must the copy assignment operator return a reference/const reference? [duplicate]

In C++, the concept of returning reference from the copy assignment operator is unclear to me. Why can't the copy assignment operator return a copy of the new object? In addition, if I have class A , and the following:

The operator= is defined as follows:

  • operator-overloading
  • copy-constructor
  • assignment-operator

Azeem's user avatar

  • 4 There's no such requirement. But if you want to stick to the principle of least surprize you'll return A& just like a=b is an lvalue expression referring to a in case a and b are ints. –  sellibitze Commented Jun 24, 2010 at 6:23
  • @MattMcNabb Thank you for letting me know! Will do that –  bks Commented Feb 20, 2015 at 6:35
  • Why cant we return A* from the copy assignment operator I guess the chaining assignment would still work properly. Can anyone help understand the perils of returning A* if there are any. –  krishna Commented Mar 19, 2015 at 7:35
  • 1 Note: Since C++11 there is also the move-assignment operator , all the same logic in this Q & A also applies to the move-assignment operator. In fact they could both be the same function if declared as A & operator=(A a); , i.e. taking the argument by value. –  M.M Commented Mar 27, 2015 at 2:28
  • 1 There is now also a C++ Core Guideline regarding this, explaining the historical context as well. –  MakisH Commented Feb 22, 2022 at 20:38

8 Answers 8

A bit of clarification as to why it's preferable to return by reference for operator= versus return by value --- as the chain a = b = c will work fine if a value is returned.

If you return a reference, minimal work is done. The values from one object are copied to another object.

However, if you return by value for operator= , you will call a constructor AND destructor EACH time that the assignment operator is called!!

In sum, there is nothing gained by returning by value, but a lot to lose.

( Note : This isn't meant to address the advantages of having the assignment operator return an lvalue. Read the other posts for why that might be preferable)

Alex Collins's user avatar

  • What I find annoying is that you're allowed to return a stupid type. I think it should enforce the non-const ref of the type... Although to delete the function, whatever it returns doesn't matter much. –  Alexis Wilke Commented Feb 4, 2021 at 23:50

Strictly speaking, the result of a copy assignment operator doesn't need to return a reference, though to mimic the default behavior the C++ compiler uses, it should return a non-const reference to the object that is assigned to (an implicitly generated copy assignment operator will return a non-const reference - C++03: 12.8/10). I've seen a fair bit of code that returns void from copy assignment overloads, and I can't recall when that caused a serious problem. Returning void will prevent users from 'assignment chaining' ( a = b = c; ), and will prevent using the result of an assignment in a test expression, for example. While that kind of code is by no means unheard of, I also don't think it's particularly common - especially for non-primitive types (unless the interface for a class intends for these kinds of tests, such as for iostreams).

I'm not recommending that you do this, just pointing out that it's permitted and that it doesn't seem to cause a whole lot of problems.

These other SO questions are related (probably not quite dupes) that have information/opinions that might be of interest to you.

  • Has anyone found the need to declare the return parameter of a copy assignment operator const?
  • Overloading assignment operator in C++

Community's user avatar

  • I found it useful to return void on the assignment operator when I needed to prevent the automatic destruction of objects as they came of the stack. For ref-counted objects, you don't want destructors being called when you don't know about them. –  cjcurrie Commented Jan 12, 2013 at 13:54

When you overload operator= , you can write it to return whatever type you want. If you want to badly enough, you can overload X::operator= to return (for example) an instance of some completely different class Y or Z . This is generally highly inadvisable though.

In particular, you usually want to support chaining of operator= just like C does. For example:

That being the case, you usually want to return an lvalue or rvalue of the type being assigned to. That only leaves the question of whether to return a reference to X, a const reference to X, or an X (by value).

Returning a const reference to X is generally a poor idea. In particular, a const reference is allowed to bind to a temporary object. The lifetime of the temporary is extended to the lifetime of the reference to which it's bound--but not recursively to the lifetime of whatever that might be assigned to. This makes it easy to return a dangling reference--the const reference binds to a temporary object. That object's lifetime is extended to the lifetime of the reference (which ends at the end of the function). By the time the function returns, the lifetime of the reference and temporary have ended, so what's assigned is a dangling reference.

Of course, returning a non-const reference doesn't provide complete protection against this, but at least makes you work a little harder at it. You can still (for example) define some local, and return a reference to it (but most compilers can and will warn about this too).

Returning a value instead of a reference has both theoretical and practical problems. On the theoretical side, you have a basic disconnect between = normally means and what it means in this case. In particular, where assignment normally means "take this existing source and assign its value to this existing destination", it starts to mean something more like "take this existing source, create a copy of it, and assign that value to this existing destination."

From a practical viewpoint, especially before rvalue references were invented, that could have a significant impact on performance--creating an entire new object in the course of copying A to B was unexpected and often quite slow. If, for example, I had a small vector, and assigned it to a larger vector, I'd expect that to take, at most, time to copy elements of the small vector plus a (little) fixed overhead to adjust the size of the destination vector. If that instead involved two copies, one from source to temp, another from temp to destination, and (worse) a dynamic allocation for the temporary vector, my expectation about the complexity of the operation would be entirely destroyed. For a small vector, the time for the dynamic allocation could easily be many times higher than the time to copy the elements.

The only other option (added in C++11) would be to return an rvalue reference. This could easily lead to unexpected results--a chained assignment like a=b=c; could destroy the contents of b and/or c , which would be quite unexpected.

That leaves returning a normal reference (not a reference to const, nor an rvalue reference) as the only option that (reasonably) dependably produces what most people normally want.

Jerry Coffin's user avatar

  • I don't see which danger situation you are referring to in the "Returning a const reference" part; if someone writes const T &ref = T{} = t; then it is a dangling reference regardless of whether operator= returned T& or T const & . Ironically it is fine if the operator= returned by value! –  M.M Commented Feb 19, 2015 at 3:44
  • @MattMcNabb: Oops--that was supposed to say lvalue reference . Thanks for pointing it out (because yes, an rvalue reference is clearly a bad idea here). –  Jerry Coffin Commented Mar 27, 2015 at 2:45

It's partly because returning a reference to self is faster than returning by value, but in addition, it's to allow the original semantics that exist in primitive types.

Puppy's user avatar

  • Not going to vote down, but I'd like to point out that returning by value would make no sense. Imagine (a = b = c) if (a = b) returned 'a' by value. Your latter point is very legit. –  stinky472 Commented Jun 25, 2010 at 12:45
  • 5 You'd get (a = (b = c)), I believe, which would still produce the intended result. Only if you did (a = b) = c would it be broken. –  Puppy Commented Jun 25, 2010 at 12:51

operator= can be defined to return whatever you want. You need to be more specific as to what the problem actually is; I suspect that you have the copy constructor use operator= internally and that causes a stack overflow, as the copy constructor calls operator= which must use the copy constructor to return A by value ad infinitum.

MSN's user avatar

  • That would be a lame (and unusual) copy-ctor implementation. The reason to return A& from A::operator= is different in most cases. –  jpalecek Commented Jun 25, 2010 at 11:53
  • @jpalecek, I agree, but given the original post and lack of clarity when stating the actual problem, it is most likely that the assignment operator executing results in a stackoverflow due to infinite recursion. If there is another explanation for this question I would love to know it. –  MSN Commented Jun 28, 2010 at 21:18
  • @MSN I dont know it was his problem or not . But surely your post here has addressed my problem +1 for that –  Invictus Commented Apr 1, 2012 at 18:39

There is no core language requirement on the result type of a user-defined operator= , but the standard library does have such a requirement:

C++98 §23.1/3:

” The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

C++98 §23.1/4:

” In Table 64, T is the type used to instantiate the container, t is a value of T , and u is a value of (possibly const ) T .

Returning a copy by value would still support assignment chaining like a = b = c = 42; , because the assignment operator is right-associative, i.e. this is parsed as a = (b = (c = 42)); . But returning a copy would prohibit meaningless constructions like (a = b) = 666; . For a small class returning a copy could conceivably be most efficient, while for a larger class returning by reference will generally be most efficient (and a copy, prohibitively inefficient).

Until I learned about the standard library requirement I used to let operator= return void , for efficiency and to avoid the absurdity of supporting side-effect based bad code.

With C++11 there is additionally the requirement of T& result type for default -ing the assignment operator, because

C++11 §8.4.2/1:

” A function that is explicitly defaulted shall […] have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T ”, where T is the name of the member function’s class) as if it had been implicitly declared

Cheers and hth. - Alf's user avatar

  • Copy assignment should not be void , otherwise assignment chain will not work
  • Copy assignment should not return a value, otherwise unnecessary copy constructor and destructor will be called
  • Copy assignment should not return rvalue reference cos it may have the assigned object moved . Again take the assignment chain for example

Silentroar's user avatar

I guess, because user defined object should behave like builtin types. For example:

baz's user avatar

Not the answer you're looking for? Browse other questions tagged c++ operator-overloading copy-constructor assignment-operator or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • From PHP to JavaScript to Kubernetes: how one backend engineer evolved over time
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • What does a new user need in a homepage experience on Stack Overflow?

Hot Network Questions

  • What's the counterpart to "spheroid" for a circle? There's no "circoid"
  • Capitalization and Proper Nouns
  • How do I do calculations with a sliding window while being memory-efficient?
  • In the US, can I buy iPhone and Android phones and claim them as expense?
  • Can I use rear (thru) axle with crack for a few rides, before getting a new one?
  • grep command fails with out-of-memory error
  • Why are the titles of certain types of works italicized?
  • What (if any) pre-breathes were "attempted" on the ISS, and why?
  • Can pedestrians and cyclists board shuttle trains in the Channel Tunnel?
  • Can the speed of light inhibit the synchronisation of a power grid?
  • Are Experimental Elixirs Magic Items?
  • Is my electrical rough-in code compliant?
  • 1970s? Novel, a man is stuck/trapped? in a city where the other people are fooled/conned into believing things are better than they are
  • What is the lesson of the Book of Iyov for the "average" person
  • Can you successfully substitute pickled onions for baby onions in Coq Au Vin?
  • When a submarine blows its ballast and rises, where did the energy for the ascent come from?
  • Efficiently tagging first and last of each object matching condition
  • The hat-check problem
  • How does quantum field theory affect the ontological tenability of composite objects?
  • Everyone hates this Key Account Manager, but company won’t act
  • How to determine if a set is countable or uncountable?
  • How can I push back on my co-worker's changes that I disagree with?
  • Is there anything that stops the majority shareholder(s) from destroying company value?
  • Why don't we observe protons deflecting in J.J. Thomson's experiment?

the copy assignment operator

IMAGES

  1. Programming example: Copy assignment operator

    the copy assignment operator

  2. PPT

    the copy assignment operator

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

    the copy assignment operator

  4. 2 Wrong Way to Learn Copy Assignment Operator in C++ With Example

    the copy assignment operator

  5. Copy assignment operator

    the copy assignment operator

  6. PPT

    the copy assignment operator

COMMENTS

  1. Copy assignment operator

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

  2. c++

    A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&. So for example: struct X {. int a; // an assignment operator which is not a copy assignment operator. X &operator=(int rhs) { a = rhs; return *this ...

  3. Copy Constructor vs Assignment Operator in C++

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

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

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

  5. Copy assignment operator

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

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

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

  8. Assignment operators

    For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment.. Compound assignment replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b. [] Assignment operator syntaThe assignment expressions have the form

  9. 21.12

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

  10. Copy constructors, assignment operators,

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

  11. Copy assignment operator

    The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial T has no non-static data members of volatile-qualified type (since C++14) 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 ...

  12. 21.13

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

  13. The copy constructor and assignment operator

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

  14. Copy assignment operators (C++ only)

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

  15. Shallow Copy and Deep Copy in C++

    Shallow Copy and Deep Copy in C++. In general, creating a copy of an object means to create an exact replica of the object having the same literal value, data type, and resources. There are two ways that are used by C++ compiler to create a copy of objects. // Default assignment operator. Depending upon the resources like dynamic memory held by ...

  16. 14.14

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

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

    The one thing to be careful of is to make sure that the swap method is a true swap, and not the default std::swap which uses the copy constructor and assignment operator itself. Typically a memberwise swap is used. std::swap works and is 'no-throw' guaranteed with all basic types and pointer types. Most smart pointers can also be swapped with a ...

  18. Copy Constructor in C++

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

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

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

  20. The rule of three/five/zero

    Rule of three. If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three. Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special ...

  21. Copy assignment operators (C++ only)

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