C++ Default Copy Assignment Constructors

In the C++programming language, the assignment operator, , is the operator used for assignment. Like most other operators in C++, it can be overloaded.

The copy assignment operator, often just called the "assignment operator", is a special case of assignment operator where the source (right-hand side) and destination (left-hand side) are of the same class type. It is one of the special member functions, which means that a default version of it is generated automatically by the compiler if the programmer does not declare one. The default version performs a memberwise copy, where each member is copied by its own copy assignment operator (which may also be programmer-declared or compiler-generated).

The copy assignment operator differs from the copy constructor in that it must clean up the data members of the assignment's target (and correctly handle self-assignment) whereas the copy constructor assigns values to uninitialized data members.[1] For example:

My_Arrayfirst;// initialization by default constructorMy_Arraysecond(first);// initialization by copy constructorMy_Arraythird=first;// Also initialization by copy constructorsecond=third;// assignment by copy assignment operator

Return value of overloaded assignment operator[edit]

The language permits an overloaded assignment operator to have an arbitrary return type (including ). However, the operator is usually defined to return a reference to the assignee. This is consistent with the behavior of assignment operator for built-in types (returning the assigned value) and allows for using the operator invocation as an expression, for instance in control statements or in chained assignment. Also, the C++ Standard Library requires this behavior for some user-supplied types.[2]

Overloading copy assignment operator[edit]

When deep copies of objects have to be made, exception safety should be taken into consideration. One way to achieve this when resource deallocation never fails is:

  1. Acquire new resources
  2. Release old resources
  3. Assign the new resources' handles to the object
classMy_Array{int*array;intcount;public:My_Array&operator=(constMy_Array&other){if(this!=&other)// protect against invalid self-assignment{// 1: allocate new memory and copy the elementsint*new_array=newint[other.count];std::copy(other.array,other.array+other.count,new_array);// 2: deallocate old memorydelete[]array;// 3: assign the new memory to the objectarray=new_array;count=other.count;}// by convention, always return *thisreturn*this;}// ...};

However, if a no-fail (no-throw) swap function is available for all the member subobjects and the class provides a copy constructor and destructor (which it should do according to the rule of three), the most straightforward way to implement copy assignment is as follows:[3]

public:voidswap(My_Array&other)// the swap member function (should never fail!){// swap all the members (and base subobject, if applicable) with otherusingstd::swap;// because of ADL the compiler will use // custom swap for members if it exists// falling back to std::swapswap(array,other.array);swap(count,other.count);}My_Array&operator=(My_Arrayother)// note: argument passed by value!{// swap this with otherswap(other);// by convention, always return *thisreturn*this;// other is destroyed, releasing the memory}

Assignment between different classes[edit]

C++ supports assignment between different classes, both via implicit copy constructor and assignment operator, if the destination instance class is the ancestor of the source instance class:

classAncestor{public:inta;};classDescendant:publicAncestor{public:intb;};intmain(){Descendantd;Ancestora(d);Ancestorb(d);a=d;return0;}

Copying from ancestor to descendant objects, which could leave descendant's fields uninitialized, is not permitted.

See also[edit]

References[edit]

External links[edit]

  1. ^Stroustrup, Bjarne (2000). The C++ Programming Language (3 ed.). Addison-Wesley. p. 244. ISBN 978-0-201-70073-2. 
  2. ^Working Draft, Standard for Programming Language C++, Section 17.6.3.1, Table 23; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
  3. ^Sutter, H.; Alexandrescu, A. (October 2004), C++ Coding Standards, Addison-Wesley, ISBN 0-321-11358-6 

Copy Constructors and Copy Assignment Operators (C++)

Note

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

    causes the value of to be copied to .

  • Initialization: Initialization occurs when a new object is declared, when arguments are passed to functions by value, or when values are returned from functions by value.

    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 a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows.

  • By using the assignment operator together with a reference to the class type as the return type and the parameter that is passed by reference—for example .

  • By using the copy constructor.

    If you do not declare a copy constructor, the compiler generates a member-wise copy constructor for you. If you do not declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor does not suppress the compiler-generated copy assignment operator, nor vice versa. If you implement either one, we recommend that you also implement the other one so that the meaning of the code is clear.

    The copy constructor takes an argument of type class-name&, where class-name is the name of the class for which the constructor is defined. For example:

Note

Make the type of the copy constructor's argument const class-name& whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also enables copying 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 constclass-name&. In such a case, the compiler-generated copy constructor's argument is also const.

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

Compiler-generated assignment operators follow the same pattern with regard to const. They take a single argument of type class-name& unless the assignment operators in all base and member classes take arguments of type constclass-name&. In this case, the class's generated assignment operator takes a const argument.

Note

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

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

For more information about overloaded assignment operators, see Assignment.

Comments

Leave a Reply

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