/ | ||||
(C++11) | ||||
(C++11) |
(C++11) | ||||
(C++20) | ||||
(C++20) |
(C++11) | ||||
expression |
pointer |
specifier | ||||
specifier (C++11) | ||||
specifier (C++11) |
(C++11) | ||||
(C++11) |
(C++11) | ||||
(C++11) |
General | ||||
(C++11) | ||||
(C++20) | ||||
(C++26) | ||||
(C++11) | ||||
(C++11) |
-expression | ||||
-expression | ||||
-expression |
(C++11) | ||||
(C++11) | ||||
(C++17) | ||||
(C++20) |
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); | |
remainder 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 . |
Definitions Assignment operator syntax Built-in simple assignment operator Assignment from an expression Assignment from a non-expression initializer clause Built-in compound assignment operator Example Defect reports See also |
Copy assignment replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is performed in a special member function, described in copy 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 performed in 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 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 assignment expressions have the form
target-expr new-value | (1) | ||||||||
target-expr op new-value | (2) | ||||||||
target-expr | - | the expression to be assigned to |
op | - | one of *=, /= %=, += -=, <<=, >>=, &=, ^=, |= |
new-value | - | the expression (until C++11) (since C++11) to assign to the target |
If new-value is not an expression, the assignment expression will never match an overloaded compound assignment operator. | (since C++11) |
For the built-in simple assignment, the object referred to by target-expr is modified by replacing its value with the result of new-value . target-expr must be a modifiable lvalue.
The result of a built-in simple assignment is an lvalue of the type of target-expr , referring to target-expr . If target-expr is a bit-field , the result is also a bit-field.
If new-value is an expression, it is implicitly converted to the cv-unqualified type of target-expr . When target-expr is a bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.
If target-expr and new-value identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same).
If the type of target-expr is volatile-qualified, the assignment is deprecated, unless the (possibly parenthesized) assignment expression is a or an . | (since C++20) |
new-value is only allowed not to be an expression in following situations: is of a , and new-value is empty or has only one element. In this case, given an invented variable t declared and initialized as T t = new-value , the meaning of x = new-value is x = t. is of class type. In this case, new-value is passed as the argument to the assignment operator function selected by . <double> z; z = {1, 2}; // meaning z.operator=({1, 2}) z += {1, 2}; // meaning z.operator+=({1, 2}) int a, b; a = b = {1}; // meaning a = b = 1; a = {1} = b; // syntax error | (since C++11) |
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); | ||
The behavior of every built-in compound-assignment expression target-expr op = new-value is exactly the same as the behavior of the expression target-expr = target-expr op new-value , except that target-expr is evaluated only once.
The requirements on target-expr and new-value of built-in simple assignment operators also apply. Furthermore:
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 &, ); | ||
Possible output:
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 | compound assignment operators for volatile -qualified types were inconsistently deprecated | none of them is deprecated | |
C++11 | an assignment from a non-expression initializer clause to a scalar value would perform direct-list-initialization | performs copy-list- initialization instead | |
C++20 | bitwise compound assignment operators for volatile types were deprecated while being useful for some platforms | they are not 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 |
Spring 2022, self-assignment.
Show Lecture.Self-assignment as a slide show.
This illustrates the danger of self-assignment.
That is, when an object containing pointers or other handles to external resources is assigned to itself, you’ve got to be careful in operator= , or you might destroy your data before you copy it to yourself.
When a class contains a handle to external data, the copy constructor generally follows this pattern:
That is, don’t just copy the handle (pointer, file descriptor, etc.). Instead you have to make an actual copy of the resource (copy the memory from new , create a new temporary file and copy the contents, etc.).
Of course, this is a copy constructor, not an assignment operator, so there was no previous value. We are constructing .
When a class contains a handle to external data, the assignment operator ( operator= ) generally follows this pattern:
What happens inside a = a ?
The copy ctor calls operator= ; as complex objects often do. Initialize data = nullptr so the initial delete data is ok.
Assignment operators in programming are symbols used to assign values to variables. They offer shorthand notations for performing arithmetic operations and updating variable values in a single step. These operators are fundamental in most programming languages and help streamline code while improving readability.
Table of Content
Assignment operators are used in programming to assign values to variables. We use an assignment operator to store and update data within a program. They enable programmers to store data in variables and manipulate that data. The most common assignment operator is the equals sign ( = ), which assigns the value on the right side of the operator to the variable on the left side.
Below is a table summarizing common assignment operators along with their symbols, description, and examples:
Operator | Description | Examples |
---|---|---|
= (Assignment) | Assigns the value on the right to the variable on the left. | assigns the value 10 to the variable x. |
+= (Addition Assignment) | Adds the value on the right to the current value of the variable on the left and assigns the result to the variable. | is equivalent to |
-= (Subtraction Assignment) | Subtracts the value on the right from the current value of the variable on the left and assigns the result to the variable. | is equivalent to |
*= (Multiplication Assignment) | Multiplies the current value of the variable on the left by the value on the right and assigns the result to the variable. | is equivalent to |
/= (Division Assignment) | Divides the current value of the variable on the left by the value on the right and assigns the result to the variable. | is equivalent to |
%= (Modulo Assignment) | Calculates the modulo of the current value of the variable on the left and the value on the right, then assigns the result to the variable. | is equivalent to |
Here are the implementation of Assignment Operator in C language:
Here are the implementation of Assignment Operator in C++ language:
Here are the implementation of Assignment Operator in java language:
Here are the implementation of Assignment Operator in python language:
Here are the implementation of Assignment Operator in C# language:
Here are the implementation of Assignment Operator in javascript language:
In conclusion, assignment operators in programming are essential tools for assigning values to variables and performing operations in a concise and efficient manner. They allow programmers to manipulate data and control the flow of their programs effectively. Understanding and using assignment operators correctly is fundamental to writing clear, efficient, and maintainable code in various programming languages.
Similar reads.
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.
I'm reading a book on template programming, and one of the examples they have code that does a self check in a templated assignment operator. Basically it's something like the following:
Now, from my understanding, since the templated assignment operator doesn't prevent the default assignment operator from being generated, for cases where O = T, the default assignment operator will always be selected over the templated version. That is, in this situation it will never be the case that O = T.
What I'm wondering is whether my understanding of this is correct. If it is, is there some sort of a tricky hierarchy (like if I derive Foo from something else or if it is derived from something else) where the assignment operator will print out "success"?
I've tried several things but I can't really get it to do that.
Thanks in advance
Either you're right, or both MSVC 11 and g++ 4.7.1 got it wrong.
I.e., normally that templated assignment operator will not be called: the automatically generated copy assignment operator will be called.
To output "success", do like this, and hope that compiler uses Empty Base class Optimization (EBO):
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 .
COMMENTS
To answer my rhetorical question: It means that a well-designed assignment operator should not need to check for self-assignment. Assigning an object to itself should work correctly (i.e. have the end-effect of "doing nothing") without performing an explicit check for self-assignment.
If we have an object say a1 of type Array and if we have a line like a1 = a1 somewhere, the program results in unpredictable behavior because there is no self assignment check in the above code. To avoid the above issue, self assignment check must be there while overloading assignment operator. For example, following code does self assignment check.
I have always seen the recommendation that the check is done explicitly. You've been looking in the wrong places, see e.g. C++ Coding Standards by Sutter & Alexandrescu. Self-assignment is exceedingly rare in most programs, so an explicit check adds a small cost to every self-assignment even though the check is almost always false.
The compiler will generate memberwise copying and assignment by calling each member's operator/constructor in turn. That works fine. Sometimes people belive that the self-assignment test is an optimization, but it can just as well be a pessimisation - adding an extra check to all assignments.
Second, the self-assignment check may be omitted in classes that can naturally handle self-assignment. Consider this Fraction class assignment operator that has a self-assignment guard: ... Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete ...
In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions
In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions
Now, one more very important point about the assignment operator: YOU MUST CHECK FOR SELF-ASSIGNMENT! This is especially important when your class does its own memory allocation. Here is why: The typical sequence of operations within an assignment operator is usually something like this: MyClass& MyClass::operator=(const MyClass &rhs) { // 1.
If self-assignment can be handled without any extra code, don't add any extra code. But do add a comment so others will know that your assignment operator gracefully handles self-assignment: Example 1a: Fred& Fred::operator= (const Fred& f) {. // This gracefully handles self assignment. *p_ = *f.p_; return *this;
The steps in writing our own assignment operator are the following: Check for self-assignment. Delete old memory. Allocate new memory. Copy the data. Return *this. Notice the worry about self-assignment, as in "A = A". We need to check for this both to avoid unnecessary work and to avoid problems later when we delete the old memory.
c++11. Move assignment operators must also be protected against self-assignment. However, the logic for many such operators is based on std::swap, which can handle swapping from/to the same memory just fine. So if your move assignment logic is nothing more than a series of swap operations, then you do not need self-assignment protection.
Checking for self assignment can be necessary when the object contains raw pointers that have to be deep-copied, because the standard "delete the pointer in *this, reallocate it, and copy from the rhs object to *this" doesn't work since "delete the pointer in *this" would also delete the pointer in rhs in the self-assignment case.
Assignment Operator General Outline. When a class contains a handle to external data, the assignment operator ( operator=) generally follows this pattern: Get rid of the old external data ( delete memory, close network socket, delete temporary file, unlock semaphore, etc.). Copy the resource from the other object to this object.
In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions
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.
The first approach is more standard so if you see the second in practice it is likely a good developer will question if this is self-assignment safe or not. If you had a different structure: struct Foo {. std::shared_ptr<Bar> m_p; }; That would also be self-assignment safe if you just use m_p = src.m_p; .
Assignment Operator General Outline. When a class contains a handle to external data, the assignment operator ( operator=) generally follows this pattern: Get rid of the old external data ( delete memory, close network socket, delete temporary file, unlock semaphore, etc.). Copy the resource from the other object to this object.
The copy assignment operator uses std::move() rather than swap() to achieve safe self-assignment and a strong exception guarantee. The move assignment operator uses a move (via the method parameter) and swap. The move constructor is not strictly necessary, but defining a move constructor along with a move assignment operator is conventional for classes that support move operations.
Assignment operators are used in programming to assign values to variables. We use an assignment operator to store and update data within a program. They enable programmers to store data in variables and manipulate that data. The most common assignment operator is the equals sign (=), which assigns the value on the right side of the operator to ...
I.e., normally that templated assignment operator will not be called: the automatically generated copy assignment operator will be called. To output "success", do like this, and hope that compiler uses Empty Base class Optimization (EBO): #include <iostream>. template <typename T>. class Foo;