/ | ||||
(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) |
Customizes the C++ operators for operands of user-defined types.
Syntax Overloaded operators Static overloaded operators Restrictions Canonical implementations Assignment operator Stream extraction and insertion Function call operator Increment and decrement Binary arithmetic operators Comparison operators Array subscript operator Bitwise arithmetic operators Boolean negation operator Rarely overloaded operators Notes Keywords Example Defect reports See also External links |
Overloaded operators are functions with special function names:
op | (1) | ||||||||
type | (2) | ||||||||
| (3) | ||||||||
| (4) | ||||||||
suffix-identifier | (5) | (since C++11) | |||||||
(6) | (since C++20) | ||||||||
op | - | any of the following operators:+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= <=>(since C++20) && || ++ -- , ->* -> ( ) [ ] |
When an operator appears in an expression , and at least one of its operands has a class type or an enumeration type , then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following:
Expression | As member function | As non-member function | Example |
---|---|---|---|
@a | (a).operator@ ( ) | operator@ (a) | ! calls .operator!() |
a@b | (a).operator@ (b) | operator@ (a, b) | << 42 calls .operator<<(42) |
a=b | (a).operator= (b) | cannot be non-member | Given s;, s = "abc"; calls s.operator=("abc") |
a(b...) | (a).operator()(b...) | cannot be non-member | Given r;, auto n = r(); calls r.operator()() |
a[b...] | (a).operator[](b...) | cannot be non-member | Given <int, int> m;, m[1] = 2; calls m.operator[](1) |
a-> | (a).operator-> ( ) | cannot be non-member | Given <S> p;, p->bar() calls p.operator->() |
a@ | (a).operator@ (0) | operator@ (a, 0) | Given <int>::iterator i;, i++ calls i.operator++(0) |
In this table, is a placeholder representing all matching operators: all prefix operators in @a, all postfix operators other than -> in a@, all infix operators other than = in a@b. |
In addition, for comparison operators ==, !=, <, >, <=, >=, <=>, overload resolution also considers the generated from operator== or operator<=>. | (since C++20) |
Note: for overloading co_await , (since C++20) user-defined conversion functions , user-defined literals , allocation and deallocation see their respective articles.
Overloaded operators (but not the built-in operators) can be called using function notation:
Overloaded operators that are member functions can be declared . However, this is only allowed for operator() and operator[]. Such operators can be called using function notation. However, when these operators appear in expressions, they still require an object of class type. SwapThem { template <typename T> static void operator()(T& lhs, T& rhs) { std:: (lhs, rhs); } template <typename T> static void operator[](T& lhs, T& rhs) { std:: (lhs, rhs); } }; inline constexpr SwapThem swap_them {}; void foo() { int a = 1, b = 2; swap_them(a, b); // OK swap_them[a, b]; // OK SwapThem{}(a, b); // OK SwapThem{}[a, b]; // OK SwapThem::operator()(a, b); // OK SwapThem::operator[](a, b); // OK SwapThem(a, b); // error, invalid construction SwapThem[a, b]; // error } | (since C++23) |
, , and (comma) lose their special when overloaded and behave like regular function calls even when they are used without function-call notation. | (until C++17) |
Besides the restrictions above, the language puts no other constraints on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: operator + is expected to add, rather than multiply its arguments, operator = is expected to assign, etc. The related operators are expected to behave similarly ( operator + and operator + = do the same addition-like operation). The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write a = b = c = d , because the built-in operators allow that.
Commonly overloaded operators have the following typical, canonical forms: [1]
The assignment operator ( operator = ) has special properties: see copy assignment and move assignment for details.
The canonical copy-assignment operator is expected to be safe on self-assignment , and to return the lhs by reference:
The canonical move assignment is expected to (that is, a state with class invariants intact), and either or at least leave the object in a valid state on self-assignment, and return the lhs by reference to non-const, and be noexcept: T& operator=(T&& other) noexcept { // Guard self assignment if (this == &other) return *this; // delete[]/size=0 would also be ok delete[] mArray; // release resource in *this mArray = (other.mArray, nullptr); // leave other in valid state size = (other.size, 0); return *this; } | (since C++11) |
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 depending on the value category of the argument), swaps with the parameter, and lets the destructor clean it up.
This form automatically provides strong exception guarantee , but prohibits resource reuse.
The overloads of operator>> and operator<< that take a std:: istream & or std:: ostream & as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument ( b in a @ b ), they must be implemented as non-members.
These operators are sometimes implemented as friend functions .
When a user-defined class overloads the function call operator, operator ( ) , it becomes a FunctionObject type.
An object of such a type can be used in a function call expression:
Many standard algorithms, from std:: sort to std:: accumulate accept FunctionObject s to customize behavior. There are no particularly notable canonical forms of operator ( ) , but to illustrate the usage:
When the postfix increment or decrement operator appears in an expression, the corresponding user-defined function ( operator ++ or operator -- ) is called with an integer argument 0 . Typically, it is implemented as T operator ++ ( int ) or T operator -- ( int ) , where the argument is ignored. The postfix increment and decrement operators are usually implemented in terms of the prefix versions:
Although the canonical implementations of the prefix increment and decrement operators return by reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value.
Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex + integer would compile, and not integer + complex ). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments:
Standard algorithms such as std:: sort and containers such as std:: set expect operator < to be defined, by default, for the user-provided types, and expect it to implement strict weak ordering (thus satisfying the Compare requirements). An idiomatic way to implement strict weak ordering for a structure is to use lexicographical comparison provided by std::tie :
Typically, once operator < is provided, the other relational operators are implemented in terms of operator < .
Likewise, the inequality operator is typically implemented in terms of operator == :
When three-way comparison (such as std::memcmp or std::string::compare ) is provided, all six two-way comparison operators may be expressed through that:
The inequality operator is automatically generated by the compiler if operator== is defined. Likewise, the four relational operators are automatically generated by the compiler if the three-way comparison operator operator<=> is defined. operator== and operator!=, in turn, are generated by the compiler if operator<=> is defined as defaulted: Record { name; unsigned int floor; double weight; auto operator<=>(const Record&) const = default; }; // records can now be compared with ==, !=, <, <=, >, and >=See for details. | (since C++20) |
User-defined classes that provide array-like access that allows both reading and writing typically define two overloads for operator [ ] : const and non-const variants:
Alternatively, they can be expressed as a single member function template using an : T { decltype(auto) operator[](this auto& self, idx) { return self.mVector[idx]; } }; | (since C++23) |
If the value type is known to be a scalar type, the const variant should return by value.
Where direct access to the elements of the container is not wanted or not possible or distinguishing between lvalue c [ i ] = v ; and rvalue v = c [ i ] ; usage, operator [ ] may return a proxy. See for example std::bitset::operator[] .
operator[] can only take one subscript. In order to provide multidimensional array access semantics, e.g. to implement a 3D array access a[i][j][k] = x;, operator[] has to return a reference to a 2D plane, which has to have its own operator[] which returns a reference to a 1D row, which has to have operator[] which returns a reference to the element. To avoid this complexity, some libraries opt for overloading operator() instead, so that 3D access expressions have the Fortran-like syntax a(i, j, k) = x;. | (until C++23) |
operator[] can take any number of subscripts. For example, an operator[] of a 3D array class declared as T& operator[]( x, y, z); can directly access the elements. #include <cassert> #include <iostream> template<typename T, Z, Y, X> struct Array3d { <T, X * Y * Z> m{}; constexpr T& operator[]( z, y, x) // C++23 { (x < X and y < Y and z < Z); return m[z * Y * X + y * X + x]; } }; int main() { Array3d<int, 4, 3, 2> v; v[3, 2, 1] = 42; << "v[3, 2, 1] = " << v[3, 2, 1] << '\n'; }Output: | (since C++23) |
User-defined classes and enumerations that implement the requirements of BitmaskType are required to overload the bitwise arithmetic operators operator & , operator | , operator ^ , operator~ , operator & = , operator | = , and operator ^ = , and may optionally overload the shift operators operator << operator >> , operator >>= , and operator <<= . The canonical implementations usually follow the pattern for binary arithmetic operators described above.
The operator operator! is commonly overloaded by the user-defined classes that are intended to be used in boolean contexts. Such classes also provide a user-defined conversion function to boolean type (see for the standard library example), and the expected behavior of operator! is to return the value opposite of operator bool. | (until C++11) |
Since the built-in operator ! performs , user-defined classes that are intended to be used in boolean contexts could provide only operator bool and need not overload operator!. | (since C++11) |
The following operators are rarely overloaded:
macro | Value | Std | Feature |
---|---|---|---|
202207L | (C++23) | static operator() | |
202211L | (C++23) | static operator[] |
[ edit ] example, [ 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++98 | the non-member prefix increment operator could only have a parameter of class or enumeration type | no type requirement |
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 |
on StackOverflow C++ FAQ |
In C++, the assignment operator forms the backbone of many algorithms and computational processes by performing a simple operation like assigning a value to a variable. It is denoted by equal sign ( = ) and provides one of the most basic operations in any programming language that is used to assign some value to the variables in C++ or in other words, it is used to store some kind of information.
The right-hand side value will be assigned to the variable on the left-hand side. The variable and the value should be of the same data type.
The value can be a literal or another variable of the same data type.
In C++, the assignment operator can be combined into a single operator with some other operators to perform a combination of two operations in one single statement. These operators are called Compound Assignment Operators. There are 10 compound assignment operators in C++:
Lets see each of them in detail.
In C++, the addition assignment operator (+=) combines the addition operation with the variable assignment allowing you to increment the value of variable by a specified expression in a concise and efficient way.
This above expression is equivalent to the expression:
The subtraction assignment operator (-=) in C++ enables you to update the value of the variable by subtracting another value from it. This operator is especially useful when you need to perform subtraction and store the result back in the same variable.
In C++, the multiplication assignment operator (*=) is used to update the value of the variable by multiplying it with another value.
The division assignment operator divides the variable on the left by the value on the right and assigns the result to the variable on the left.
The modulus assignment operator calculates the remainder when the variable on the left is divided by the value or variable on the right and assigns the result to the variable on the left.
This operator performs a bitwise AND between the variable on the left and the value on the right and assigns the result to the variable on the left.
The bitwise OR assignment operator performs a bitwise OR between the variable on the left and the value or variable on the right and assigns the result to the variable on the left.
The bitwise XOR assignment operator performs a bitwise XOR between the variable on the left and the value or variable on the right and assigns the result to the variable on the left.
The left shift assignment operator shifts the bits of the variable on the left to left by the number of positions specified on the right and assigns the result to the variable on the left.
The right shift assignment operator shifts the bits of the variable on the left to the right by a number of positions specified on the right and assigns the result to the variable on the left.
Also, it is important to note that all of the above operators can be overloaded for custom operations with user-defined data types to perform the operations we want.
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 am using msvc compiler with C++ 23
I have a situation like this (class shouldn't be moveable, only copyable):
MyClass m = MyClass{}; //tries to use move
It tries to move the newly constructed class. I realize that this is natural since MyClass{} is an r-value.
Is there anything that I can do to the class to make this possible? Make the compiler understand that I want it to use copy since move is deleted, so that MyClass m = MyClass{}; works?
Error message:
Are you SURE you are actually compiling with C++23? Modern MSVC supports C++23, but it defaults to C++14. To actually enable C++23, you need to use the /std flag in your configuration.
In C++17 and later, MyClass m = MyClass{}; is optimized to be identical to MyClass m{}; but that is not the case in earlier versions.
Your code compiles fine in msvc v19 using /std:c++latest .
Online Demo
IMAGES
VIDEO
COMMENTS
4. Yes, you can assign one instance of a struct to another using a simple assignment statement. In the case of non-pointer or non pointer containing struct members, assignment means copy. In the case of pointer struct members, assignment means pointer will point to the same address of the other pointer.
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 ...
1. "=": This is the simplest assignment operator. This operator is used to assign the value on the right to the variable on the left. Example: a = 10; b = 20; ch = 'y'; 2. "+=": This operator is combination of '+' and '=' operators.This operator first adds the current value of the variable on left to the value on the right and then assigns the result to the variable on the left.
Code language:C++(cpp) The = assignment operator is called a simple assignment operator. It assigns the value of the left operand to the right operand. Besides the simple assignment operator, C supports compound assignment operators. A compound assignment operator performs the operation specified by the additional operator and then assigns the ...
Simple assignment operator. Assigns values from right side operands to left side operand. C = A + B will assign the value of A + B to C. +=. Add AND assignment operator. It adds the right operand to the left operand and assign the result to the left operand. C += A is equivalent to C = C + A. -=.
In this tutorial, you'll learn about struct types in C Programming. You will learn to define and use structures with the help of examples. In C programming, a struct (or structure) is a collection of variables (can be of different types) under a single name. ... and we cannot use the assignment operator = with it after we have declared the ...
C supports a short variant of assignment operator called compound assignment or shorthand assignment. Shorthand assignment operator combines one of the arithmetic or bitwise operators with assignment operator. For example, consider following C statements. The above expression a = a + 2 is equivalent to a += 2.
The assignment operators in C can both transform and assign values in a single operation. C provides the following assignment operators: | =. In assignment, the type of the right-hand value is converted to the type of the left-hand value, and the value is stored in the left operand after the assignment has taken place.
Assignment Operators in C are used to assign values to the variables. They come under the category of binary operators as they require two operands to operate upon. The left side operand is called a variable and the right side operand is the value. The value on the right side of the "=" is assigned to the variable on the left side of "=".
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. it is equivalent to E1 = T{E2}
15.13 Structure Assignment. Assignment operating on a structure type copies the structure. The left and right operands must have the same type. Here is an example: Notionally, assignment on a structure type works by copying each of the fields. Thus, if any of the fields has the const qualifier, that structure type does not allow assignment:
The structure in C is a user-defined data type that can be used to group items of possibly different types into a single type. The struct keyword is used to define the structure in the C programming language. The items in the structure are called its member and they can be of any valid data type. Additionally, the values of a structure are stored in contiguous memory locations.
In C, the only operation that can be applied to struct variables is assignment. Any other operation (e.g. equality check) is not allowed on struct variables. ... Prerequisite : sizeof operator in C The sizeof for a struct is not always equal to the sum of sizeof of each individual member. This is because of the padding added by the compiler to ...
21.12 — Overloading the assignment operator. 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 .
Suppose I have a structure in C++ containing a name and a number, e.g. struct person { char name[20]; int ssn; }; ... The default assignment operator in C++ uses Memberwise Assignment to copy the values. That is it effectively assigns all members to each other. In this case that would cause b to have the same values as a.
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 ...
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 ...
In C++ there's only one difference between a struct and a class: in a struct the default visibility is public while in a class it is private. Other than that you can do anything you would do in a class in a struct and it will look exactly the same. Write operator overloading in a struct as you would in a class. answered Nov 20, 2012 at 18:58.
C17 6.5.16: An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. (Lvalue conversion in this case isn't ...
In C++, the assignment operator forms the backbone of many algorithms and computational processes by performing a simple operation like assigning a value to a variable. It is denoted by equal sign ( = ) and provides one of the most basic operations in any programming language that is used to assign some value to the variables in C++ or in other ...
A operator=(const A &a) { std::cout<<"This is assignment operator."; return NULL; } You end up creating the return value of type A as per A(NULL), and as NULL is 0, that matches the A(int) constructor best, which is why you see: line 3 This is assignment operator.This is int cstr. value is 0.
@TopologicalSort m = n; will invoke the copy assignment operator, for the move assignment operator you would need m = std::move(n); instead. Also, a function that returns a named local variable may not invoke the copy constructor or the move constructor at all, if "(Named) Return Value Optimization" (aka copy elison) is used instead.