this, and most also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void). can be any type including
Explanation Builtin direct assignment Example Builtin compound assignment Example Defect reports See also |
copy assignment operator replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is a special member function, described in copy assignment operator .
operator replaces the contents of the object with the contents of , avoiding copying if possible ( may be modified). For class types, this is a special member function, described in . | (since C++11) |
For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment .
compound assignment operators replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b .
The direct assignment expressions have the form
lhs rhs | (1) | ||||||||
lhs | (2) | (since C++11) | |||||||
lhs rhs | (3) | (since C++11) | |||||||
For the built-in operator, lhs may have any non-const scalar type and rhs must be implicitly convertible to the type of lhs .
The direct assignment operator expects a modifiable lvalue as its left operand and an rvalue expression or a braced-init-list (since C++11) as its right operand, and returns an lvalue identifying the left operand after modification. The result is a bit-field if the left operand is a bit-field.
For non-class types, the right operand is first implicitly converted to the cv-unqualified type of the left operand, and then its value is copied into the object identified by left operand.
When the left operand has reference type, the assignment operator modifies the referred-to object.
If the left and the right operands identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same)
If the right operand is a has scalar type, {} is equivalent to E1 = T{}, where is the type of . {E2} is equivalent to E1 = T{E2}, where is the type of . has class type, the syntax E1 = {args...} generates a call to the assignment operator with the as the argument, which then selects the appropriate assignment operator following the rules of . Note that, if a non-template assignment operator from some non-class type is available, it is preferred over the copy/move assignment in because to non-class is an , which outranks the user-defined conversion from to a class type. | (since C++11) |
Using an lvalue of volatile-qualified non-class type as left operand of built-in direct assignment operator is deprecated, unless the assignment expression appears in an or is a . | (since C++20) |
In overload resolution against user-defined operators , for every type T , the following function signatures participate in overload resolution:
& operator=(T*&, T*); | ||
volatile & operator=(T*volatile &, T*); | ||
For every enumeration or pointer to member type T , optionally volatile-qualified, the following function signature participates in overload resolution:
operator=(T&, T); | ||
For every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signature participates in overload resolution:
operator=(A1&, A2); | ||
[ edit ] builtin compound assignment.
The compound assignment expressions have the form
lhs op rhs | (1) | ||||||||
lhs op | (2) | (since C++11) | |||||||
lhs op rhs | (3) | (since C++11) | |||||||
op | - | one of *=, /= %=, += -=, <<=, >>=, &=, ^=, |= |
lhs | - | for the built-in operator, lhs may have any arithmetic type, except when op is += or -=, which also accept pointer types with the same restrictions as + and - |
rhs | - | for the built-in operator, rhs must be implicitly convertible to lhs |
The behavior of every builtin compound-assignment expression E1 op = E2 (where E1 is a modifiable lvalue expression and E2 is an rvalue expression or a braced-init-list (since C++11) ) is exactly the same as the behavior of the expression E1 = E1 op E2 , except that the expression E1 is evaluated only once and that it behaves as a single operation with respect to indeterminately-sequenced function calls (e.g. in f ( a + = b, g ( ) ) , the += is either not started at all or is completed as seen from inside g ( ) ).
In overload resolution against user-defined operators , for every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signatures participate in overload resolution:
operator*=(A1&, A2); | ||
operator/=(A1&, A2); | ||
operator+=(A1&, A2); | ||
operator-=(A1&, A2); | ||
For every pair I1 and I2, where I1 is an integral type (optionally volatile-qualified) and I2 is a promoted integral type, the following function signatures participate in overload resolution:
operator%=(I1&, I2); | ||
operator<<=(I1&, I2); | ||
operator>>=(I1&, I2); | ||
operator&=(I1&, I2); | ||
operator^=(I1&, I2); | ||
operator|=(I1&, I2); | ||
For every optionally cv-qualified object type T , the following function signatures participate in overload resolution:
& operator+=(T*&, ); | ||
& operator-=(T*&, ); | ||
volatile & operator+=(T*volatile &, ); | ||
volatile & operator-=(T*volatile &, ); | ||
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
C++11 | for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator | removed user-defined assignment constraint | |
C++11 | E1 = {E2} was equivalent to E1 = T(E2) ( is the type of ), this introduced a C-style cast | it is equivalent to E1 = T{E2} | |
C++20 | bitwise compound assignment operators for volatile types were deprecated while being useful for some platforms | they are not deprecated | |
C++20 | compound assignment operators for volatile types were inconsistently deprecated | none of them is deprecated |
Operator precedence
Operator overloading
Common operators | ||||||
---|---|---|---|---|---|---|
a = b | ++a | +a | !a | a == b | a[...] | function call |
a(...) | ||||||
comma | ||||||
a, b | ||||||
conditional | ||||||
a ? b : c | ||||||
Special operators | ||||||
converts one type to another related type |
for Assignment operators |
Copy assignment operator.
(C++20) | ||||
(C++20) | ||||
(C++11) | ||||
(C++11) | ||||
(C++11) | ||||
(C++17) | ||||
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 Example Defect reports |
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) | |||||||
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.
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:
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) exception specification (since C++17)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
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:
The copy assignment operator for class T is trivial if all of the following is true:
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.
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move ), and selects the copy assignment if the argument is an lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.
It is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined copy assignment operator (same applies to move assignment ).
See assignment operator overloading for additional detail on the expected behavior of a user-defined copy-assignment operator.
[ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
C++14 | operator=(X&) = default was non-trivial | made trivial |
(C++11) | ||||
(C++11) | ||||
(C++11) |
General topics | ||||
Flow control | ||||
Conditional execution statements | ||||
statement |
statement |
loop | ||||
loop (C++11) |
loop | ||||
loop |
statement | ||||
statement |
(C++11) | ||||
(C++11) |
expression |
pointer | ||||
(C++11) | ||||
(C++11) |
(C++11) | ||||
Assignment operators modify the value of the object.
Operator name | Syntax | Overloadable | Prototype examples (for class T) | |
---|---|---|---|---|
Inside class definition | Outside class definition | |||
basic assignment | Yes | T& T::operator =(const T2 &b); | ||
move assignment (C++11) | Yes | T& T::operator =(const T2 &&b); | ||
addition assignment | Yes | T& T::operator +=(const T2 &b); | T& operator +=(T &a, const T2 &b); | |
subtraction assignment | Yes | T& T::operator -=(const T2 &b); | T& operator -=(T &a, const T2 &b); | |
multiplication assignment | Yes | T& T::operator *=(const T2 &b); | T& operator *=(T &a, const T2 &b); | |
division assignment | Yes | T& T::operator /=(const T2 &b); | T& operator /=(T &a, const T2 &b); | |
modulo assignment | Yes | T& T::operator %=(const T2 &b); | T& operator %=(T &a, const T2 &b); | |
bitwise AND assignment | Yes | T& T::operator &=(const T2 &b); | T& operator &=(T &a, const T2 &b); | |
bitwise OR assignment | Yes | T& T::operator |=(const T2 &b); | T& operator |=(T &a, const T2 &b); | |
bitwise XOR assignment | Yes | T& T::operator ^=(const T2 &b); | T& operator ^=(T &a, const T2 &b); | |
bitwise left shift assignment | Yes | T& T::operator <<=(const T2 &b); | T& operator <<=(T &a, const T2 &b); | |
bitwise right shift assignment | Yes | T& T::operator >>=(const T2 &b); | T& operator >>=(T &a, const T2 &b); | |
. However, essentially any value and any type can be returned (including void, i.e. no return value), yet this is unintuitive and defeats the purpose of the operators. can be any type including |
basic assignment operator replaces the contents of the object a with those of b
move assignment operator replaces the contents of the object a with those of b while minimizing copying overhead (no deep copy is performed). It complements the basic assignment operator. (since C++11)
Other assignment operators modify the contents of the object. Usually they are overloaded in classes performing mathematical operations.
Operator precedence
Common operators | ||||||
---|---|---|---|---|---|---|
a = b | ++a | +a | !a | a == b | a[b] | a(...) |
Special operators | ||||||
converts one type to another compatible type |
(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 |
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) | |||||||
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.
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:
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.
The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true:
The implicitly-declared copy assignment operator for class T is trivial if all of the following is true:
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.
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.
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.
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).
(C++11) | ||||
(C++11) | ||||
(C++11) | ||||
General | ||||
(lvalue, rvalue, xvalue) | ||||
(sequence points) | ||||
(C++11) | ||||
Literals | ||||
including | ||||
(C++11) | ||||
(C++11) | ||||
Operators | ||||
: , , , , , , , , , , | ||||
: , , , | ||||
: , , , , , , , , , , , , | ||||
: , , | ||||
: , , , , , | ||||
: , , , , , , | ||||
: , , | ||||
(C++17) | ||||
(C++11) | ||||
(C++11) | ||||
Conversions | ||||
, | ||||
Assignment operators modify the value of the object.
Operator name | Syntax | Prototype examples (for class T) | ||
---|---|---|---|---|
Inside class definition | Outside class definition | |||
simple assignment | Yes | T& T::operator =(const T2& b); | ||
addition assignment | Yes | T& T::operator +=(const T2& b); | T& operator +=(T& a, const T2& b); | |
subtraction assignment | Yes | T& T::operator -=(const T2& b); | T& operator -=(T& a, const T2& b); | |
multiplication assignment | Yes | T& T::operator *=(const T2& b); | T& operator *=(T& a, const T2& b); | |
division assignment | Yes | T& T::operator /=(const T2& b); | T& operator /=(T& a, const T2& b); | |
modulo assignment | Yes | T& T::operator %=(const T2& b); | T& operator %=(T& a, const T2& b); | |
bitwise AND assignment | Yes | T& T::operator &=(const T2& b); | T& operator &=(T& a, const T2& b); | |
bitwise OR assignment | Yes | T& T::operator |=(const T2& b); | T& operator |=(T& a, const T2& b); | |
bitwise XOR assignment | Yes | T& T::operator ^=(const T2& b); | T& operator ^=(T& a, const T2& b); | |
bitwise left shift assignment | Yes | T& T::operator <<=(const T2& b); | T& operator <<=(T& a, const T2& b); | |
bitwise right shift assignment | Yes | T& T::operator >>=(const T2& b); | T& operator >>=(T& a, const T2& b); | |
this, and most also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void). can be any type including |
Explanation Builtin direct assignment Example Builtin compound assignment Example See also |
copy assignment operator replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is a special member function, described in copy assignment operator .
move assignment operator replaces the contents of the object a with the contents of b , avoiding copying if possible ( b may be modified). For class types, this is a special member function, described in move assignment operator . (since C++11)
For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment .
compound assignment operators replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b .
For every type T , the following function signatures participate in overload resolution:
& operator=(T*&, T*); | ||
volatile & operator=(T*volatile &, T*); | ||
For every enumeration or pointer to member type T , optionally volatile-qualified, the following function signature participates in overload resolution:
operator=(T&, T ); | ||
For every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signature participates in overload resolution:
operator=(A1&, A2); | ||
For expressions E1 of any scalar type T , the following additional forms of the builtin assignment expression are allowed:
{} | (since C++11) | |
{E2} | (since C++11) | |
Note: the above includes all non-class types except reference types, array types, function types, and the type void , which are not directly assignable.
The direct assignment operator expects a modifiable lvalue as its left operand and an rvalue expression or a braced-init-list (since C++11) as its right operand, and returns an lvalue identifying the left operand after modification.
For non-class types, the right operand is first implicitly converted to the cv-unqualified type of the left operand, and then its value is copied into the object identified by left operand.
When the left operand has reference type, the assignment operator modifies the referred-to object.
If the left and the right operands identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same)
If the right operand is a {} is equivalent to E1 = T{}, where is the type of . {E2} is equivalent to E1 = T{E2}, where is the type of .For class types, the syntax generates a call to the assignment operator with the as the argument, which then selects the appropriate assignment operator following the rules of | (since C++11) |
[ edit ] builtin compound assignment.
For every pair A1 and A2, where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signatures participate in overload resolution:
operator*=(A1&, A2); | ||
operator/=(A1&, A2); | ||
operator+=(A1&, A2); | ||
operator-=(A1&, A2); | ||
For every pair I1 and I2, where I1 is an integral type (optionally volatile-qualified) and I2 is a promoted integral type, the following function signatures participate in overload resolution:
operator%=(I1&, I2); | ||
operator<<=(I1&, I2); | ||
operator>>=(I1&, I2); | ||
operator&=(I1&, I2); | ||
operator^=(I1&, I2); | ||
operator|=(I1&, I2); | ||
For every optionally cv-qualified object type T , the following function signatures participate in overload resolution:
& operator+=(T*&, ); | ||
& operator-=(T*&, ); | ||
volatile & operator+=(T*volatile &, ); | ||
volatile & operator-=(T*volatile &, ); | ||
The behavior of every builtin compound-assignment expression E1 op = E2 (where E1 is a modifiable lvalue expression and E2 is an rvalue expression or a braced-init-list (since C++11) ) is exactly the same as the behavior of the expression E1 = E1 op E2 , except that the expression E1 is evaluated only once and that it behaves as a single operation with respect to indeterminately-sequenced function calls (e.g. in f ( a + = b, g ( ) ) , the += is either not started at all or is completed as seen from inside g ( ) ).
Operator precedence
Operator overloading
Common operators | ||||||
---|---|---|---|---|---|---|
a = b | ++a | +a | !a | a == b | a[b] | a(...) |
Special operators | ||||||
converts one type to another related type |
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
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, 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?
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.
Copy-assignment for a class with a reference member variable is a no-no because you can't reassign the reference. But what about move-assignment? I tried simply move ing it but, of course, that destroys the source object when I just want to move the reference itself:
Should I just not be implementing move-assignment and sticking with move-construction only? That makes swap(C&, C&) hard to implement.
(Posted as an answer from comment as suggested by the OP)
In general if one wants to do non-trivial stuff with references in C++, one would be using reference_wrapper<T> , which is essentially a fancy value-semantic stand-in for a T& , then one would be done with it - it already provides (re)assignment and other operations. I'm sure that would make move constructor and assignment near-trivial, if not trivial (note not trivial as in per the is_trivially_* semantics).
"Reference wrapper" is added to C++03 as part of TR1, and is part of C++11.
Documentation: http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
A reference is, in some sense, a T *const with syntactic sugar on top to auto-derefence, auto-capture, and auto-lifetime extend temporaries. (note that this is not quite true, but often is in practice and practicality)
If you want a reseatable reference, C++ has those: they are called pointers. You can use an accessor to replace dereferencing with a function call if you like. The remaining feature (temporary lifetime extension) that is hard to emulate does not apply to struct members.
Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more
Post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .
Learn C++ practically and Get Certified .
Popular examples, reference materials, learn c++ interactively, introduction to c++.
C++ Operators
C++ Relational and Logical Operators
C++ Pointers to Structure
C++ Bitwise Operators
C++ operator precedence and associativity.
If there are multiple operators in a single expression, the operations are not evaluated simultaneously. Rather, operators with higher precedence have their operations evaluated first.
Let us consider an example:
Here, the multiplication operator * is of higher level precedence than the subtraction operator - . Hence, 17 * 6 is evaluated first.
As a result, the above expression is equivalent to
If we wish to evaluate 5 - 17 first, then we must enclose them within parentheses :
Note: Because there are a lot of operators in C++ with multiple levels of precedence, it is highly recommended that we use parentheses to make our code more readable.
The following table (taken from cppreference.com ) shows the precedence of C++ operators. Precedence Level 1 signifies operators of highest priority, while Precedence Level 17 signifies operators of the lowest priority.
The property of associativity will be discussed shortly.
Precedence | Operator | Description | Associativity |
---|---|---|---|
1 | :: | Scope Resolution | Left to Right |
2 | a++ a-- type( ) type{ } a( ) a[ ] . -> | Suffix/postfix increment Suffix/postfix decrement Function cast Function cast Function call Subscript Member access from an object Member access from object ptr | Left to Right |
3 | ++a --a +a -a ! ~ (type) *a &a sizeof co_await new new[ ] delete delete[] | Prefix increment Prefix decrement Unary plus Unary minus Logical NOT Bitwise NOT C style cast Indirection (dereference) Address-of Size-of await-expression Dynamic memory allocation Dynamic memory deallocation | Right to Left |
4 | .* ->* | Member object selector Member pointer selector | Left to Right |
5 | a * b a / b a % b | Multiplication Division Modulus | Left to Right |
6 | a + b a - b | Addition Subtraction | Left to Right |
7 | << >> | Bitwise left shift Bitwise right shift | Left to Right |
8 | <=> | Three-way comparison operator | Left to Right |
9 | < <= > >= | Less than Less than or equal to Greater than Greater than or equal to | Left to Right |
10 | == != | Equal to Not equal to | Left to Right |
11 | & | Bitwise AND | Left to Right |
12 | ^ | Bitwise XOR | Left to Right |
13 | | | Bitwise OR | Left to Right |
14 | && | Logical AND | Left to Right |
15 | || | Logical OR | Left to Right |
16 | a ? b : c throw co_yield = += -= *= /= %= <<= >>= &= ^= |= | Ternary Conditional throw operator yield expression (C++ 20) Assignment Addition Assignment Subtraction Assignment Multiplication Assignment Division Assignment Modulus Assignment Bitwise Shift Left Assignment Bitwise Shift Right Assignment Bitwise AND Assignment Bitwise XOR Assignment Bitwise OR Assignment | Right to Left |
17 | , | Comma operator | Left to Right |
Operator associativity is the direction from which an expression is evaluated. For example,
Take a look at a = 4; statement. The associativity of the = operator is from right to left. Hence, the value of b is assigned to a , and not in the other direction.
Also, multiple operators can have the same level of precedence (as we can see from the above table). When multiple operators of the same precedence level are used in an expression, they are evaluated according to their associativity .
Both operators += and -= operators have the same precedence. Since the associativity of these operators is from right to left, here is how the last statement is evaluated.
Table of contents.
Sorry about that.
Our premium learning platform, created with over a decade of experience and thousands of feedbacks .
Learn and improve your coding skills like never before.
C++ Tutorial
IMAGES
VIDEO
COMMENTS
Correct behavior. CWG 1527. C++11. for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) (T is the type of E1), this introduced a C-style cast.
Assignment performs implicit conversion from the value of rhs to the type of lhs and then replaces the value in the object designated by lhs with the converted value of rhs. Assignment also returns the same value as what was stored in lhs (so that expressions such as a = b = c are possible). The value category of the assignment operator is non ...
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 ...
basic assignment a = b: a becomes equal to b: N/A + = addition assignment a + = b: a becomes equal to the addition of a and b: a = a + b-= subtraction assignment a -= b: a becomes equal to the subtraction of b from a: a = a -b * = multiplication assignment a
Iteration statements (loops) for: range-for (C++11)while: do-while
Assignment operators. Assignment operators modify the value of the object. All built-in assignment operators return *this, and most user-defined overloads also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type ...
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.
Assignment operators modify the value of the object. Operator name Syntax Over load able Prototype examples (for class T) ; Inside class definition
Always return a reference to the newly altered left hand side, return *this. This is to allow operator chaining, e.g. a = b = c;. Always check for self assignment (this == &rhs). This is especially important when your class does its own memory allocation. MyClass& MyClass::operator=(const MyClass &rhs) {.
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 transfer the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors ...
Class-specific function properties virtual function: override specifier (C++11): final specifier (C++11): explicit (C++11): static
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.
From cppreference.com < cpp | languagecpp | language C++
In those situations where copy assignment cannot benefit from resource reuse (it does not manage a heap-allocated array and does not have a (possibly transitive) member that does, such as a member std::vector or std::string), there is a popular convenient shorthand: the copy-and-swap assignment operator, which takes its parameter by value (thus working as both copy- and move-assignment ...
21.12 — Overloading the assignment operator. Alex July 22, 2024. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. As of C++11, C++ also supports "Move assignment". We discuss move assignment in lesson 22.3 -- Move constructors and move assignment.
Just don't do it. The solution is simple: if the class needs to support assignment, don't use any reference members. I have a lot of classes which take reference arguments, but store them as pointers, just so the class can support assignment. Something like: struct A. {. int* myRef; A( int& ref ) : myRef( &ref ) {}
std::vector<T,Allocator>:: assign. Replaces the contents of the container. 1) Replaces the contents with count copies of value value. 2) Replaces the contents with copies of those in the range [first,last). The behavior is undefined if either argument is an iterator into *this. This overload has the same effect as overload (1) if InputIt is an ...
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.
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.
Thanks. I was a bit confused by this question, so for reference: you talk about "move assignment", but the c2 = c1 line is not a move assignment, it is a copy assignment (and thus the reference member is a problem). It should be c2 = std::move(c1), perhaps. You actually can make this work, but the problem is that there's no way to mark the ...
C++ Operators Associativity. Operator associativity is the direction from which an expression is evaluated. For example, int a = 1; int b = 4; // a will be 4 a = b; Take a look at a = 4; statement. The associativity of the = operator is from right to left. Hence, the value of b is assigned to a, and not in the other direction.. Also, multiple operators can have the same level of precedence (as ...