C++ Operator Overloading Guidelines

One of the nice features of C++ is that you can give special meanings to operators, when they are used with user-defined classes. This is called operator overloading . You can implement C++ operator overloads by providing special member-functions on your classes that follow a particular naming convention. For example, to overload the + operator for your class, you would provide a member-function named operator+ on your class.

  • = (assignment operator)
  • + - * (binary arithmetic operators)
  • += -= *= (compound assignment operators)
  • == != (comparison operators)

Here are some guidelines for implementing these operators. These guidelines are very important to follow, so definitely get in the habit early.

Assignment Operator =

The assignment operator has a signature like this: class MyClass { public: ... MyClass & operator=(const MyClass &rhs); ... } MyClass a, b; ... b = a; // Same as b.operator=(a);

Notice that the = operator takes a const-reference to the right hand side of the assignment. The reason for this should be obvious, since we don't want to change that value; we only want to change what's on the left hand side.

  • e = 42 assigns 42 to e , then returns e as the result
  • The value of e is then assigned to d , and then d is returned as the result
  • The value of d is then assigned to c , and then c is returned as the result

Now, in order to support operator chaining, the assignment operator must return some value. The value that should be returned is a reference to the left-hand side of the assignment.

Notice that the returned reference is not declared const . This can be a bit confusing, because it allows you to write crazy stuff like this: MyClass a, b, c; ... (a = b) = c; // What?? At first glance, you might want to prevent situations like this, by having operator= return a const reference. However, statements like this will work with primitive types. And, even worse, some tools actually rely on this behavior. Therefore, it is important to return a non- const reference from your operator= . The rule of thumb is, "If it's good enough for int s, it's good enough for user-defined data-types."

So, for the hypothetical MyClass assignment operator, you would do something like this: // Take a const-reference to the right-hand side of the assignment. // Return a non-const reference to the left-hand side. MyClass& MyClass::operator=(const MyClass &rhs) { ... // Do the assignment operation! return *this; // Return a reference to myself. } Remember, this is a pointer to the object that the member function is being called on. Since a = b is treated as a.operator=(b) , you can see why it makes sense to return the object that the function is called on; object a is the left-hand side.

But, the member function needs to return a reference to the object, not a pointer to the object. So, it returns *this , which returns what this points at (i.e. the object), not the pointer itself. (In C++, instances are turned into references, and vice versa, pretty much automatically, so even though *this is an instance, C++ implicitly converts it into a reference to the instance.)

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. Deallocate any memory that MyClass is using internally // 2. Allocate some memory to hold the contents of rhs // 3. Copy the values from rhs into this instance // 4. Return *this } Now, what happens when you do something like this: MyClass mc; ... mc = mc; // BLAMMO. You can hopefully see that this would wreak havoc on your program. Because mc is on the left-hand side and on the right-hand side, the first thing that happens is that mc releases any memory it holds internally. But, this is where the values were going to be copied from, since mc is also on the right-hand side! So, you can see that this completely messes up the rest of the assignment operator's internals.

The easy way to avoid this is to CHECK FOR SELF-ASSIGNMENT. There are many ways to answer the question, "Are these two instances the same?" But, for our purposes, just compare the two objects' addresses. If they are the same, then don't do assignment. If they are different, then do the assignment.

So, the correct and safe version of the MyClass assignment operator would be this: MyClass& MyClass::operator=(const MyClass &rhs) { // Check for self-assignment! if (this == &rhs) // Same object? return *this; // Yes, so skip assignment, and just return *this. ... // Deallocate, allocate new space, copy values... return *this; } Or, you can simplify this a bit by doing: MyClass& MyClass::operator=(const MyClass &rhs) { // Only do assignment if RHS is a different object from this. if (this != &rhs) { ... // Deallocate, allocate new space, copy values... } return *this; } Remember that in the comparison, this is a pointer to the object being called, and &rhs is a pointer to the object being passed in as the argument. So, you can see that we avoid the dangers of self-assignment with this check.

  • Take a const-reference for the argument (the right-hand side of the assignment).
  • Return a reference to the left-hand side, to support safe and reasonable operator chaining. (Do this by returning *this .)
  • Check for self-assignment, by comparing the pointers ( this to &rhs ).

Compound Assignment Operators += -= *=

I discuss these before the arithmetic operators for a very specific reason, but we will get to that in a moment. The important point is that these are destructive operators, because they update or replace the values on the left-hand side of the assignment. So, you write: MyClass a, b; ... a += b; // Same as a.operator+=(b) In this case, the values within a are modified by the += operator.

How those values are modified isn't very important - obviously, what MyClass represents will dictate what these operators mean.

The member function signature for such an operator should be like this: MyClass & MyClass::operator+=(const MyClass &rhs) { ... } We have already covered the reason why rhs is a const-reference. And, the implementation of such an operation should also be straightforward.

But, you will notice that the operator returns a MyClass -reference, and a non-const one at that. This is so you can do things like this: MyClass mc; ... (mc += 5) += 3;

Don't ask me why somebody would want to do this, but just like the normal assignment operator, this is allowed by the primitive data types. Our user-defined datatypes should match the same general characteristics of the primitive data types when it comes to operators, to make sure that everything works as expected.

This is very straightforward to do. Just write your compound assignment operator implementation, and return *this at the end, just like for the regular assignment operator. So, you would end up with something like this: MyClass & MyClass::operator+=(const MyClass &rhs) { ... // Do the compound assignment work. return *this; }

As one last note, in general you should beware of self-assignment with compound assignment operators as well. Fortunately, none of the C++ track's labs require you to worry about this, but you should always give it some thought when you are working on your own classes.

Binary Arithmetic Operators + - *

The binary arithmetic operators are interesting because they don't modify either operand - they actually return a new value from the two arguments. You might think this is going to be an annoying bit of extra work, but here is the secret:

Define your binary arithmetic operators using your compound assignment operators.

There, I just saved you a bunch of time on your homeworks.

So, you have implemented your += operator, and now you want to implement the + operator. The function signature should be like this: // Add this instance's value to other, and return a new instance // with the result. const MyClass MyClass::operator+(const MyClass &other) const { MyClass result = *this; // Make a copy of myself. Same as MyClass result(*this); result += other; // Use += to add other to the copy. return result; // All done! } Simple!

Actually, this explicitly spells out all of the steps, and if you want, you can combine them all into a single statement, like so: // Add this instance's value to other, and return a new instance // with the result. const MyClass MyClass::operator+(const MyClass &other) const { return MyClass(*this) += other; } This creates an unnamed instance of MyClass , which is a copy of *this . Then, the += operator is called on the temporary value, and then returns it.

If that last statement doesn't make sense to you yet, then stick with the other way, which spells out all of the steps. But, if you understand exactly what is going on, then you can use that approach.

You will notice that the + operator returns a const instance, not a const reference. This is so that people can't write strange statements like this: MyClass a, b, c; ... (a + b) = c; // Wuh...? This statement would basically do nothing, but if the + operator returns a non- const value, it will compile! So, we want to return a const instance, so that such madness will not even be allowed to compile.

  • Implement the compound assignment operators from scratch, and then define the binary arithmetic operators in terms of the corresponding compound assignment operators.
  • Return a const instance, to prevent worthless and confusing assignment operations that shouldn't be allowed.

Comparison Operators == and !=

The comparison operators are very simple. Define == first, using a function signature like this: bool MyClass::operator==(const MyClass &other) const { ... // Compare the values, and return a bool result. } The internals are very obvious and straightforward, and the bool return-value is also very obvious.

The important point here is that the != operator can also be defined in terms of the == operator, and you should do this to save effort. You can do something like this: bool MyClass::operator!=(const MyClass &other) const { return !(*this == other); } That way you get to reuse the hard work you did on implementing your == operator. Also, your code is far less likely to exhibit inconsistencies between == and != , since one is implemented in terms of the other.

cppreference.com

Search

operator overloading

Customizes the C++ operators for operands of user-defined types.

[ edit ] Syntax

Overloaded operators are functions with special function names:

[ edit ] Overloaded operators

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:

Note: for overloading 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:

[ edit ] Restrictions

  • The operators :: (scope resolution), . (member access), .* (member access through pointer to member), and ?: (ternary conditional) cannot be overloaded
  • New operators such as ** , <> , or &| cannot be created
  • The overloads of operators && , || , and , (comma) lose their special properties: short-circuit evaluation and sequencing .
  • The overload of operator -> must either return a raw pointer or return an object (by reference or by value), for which operator -> is in turn overloaded.
  • It is not possible to change the precedence, grouping, or number of operands of operators.

[ edit ] Canonical implementations

Other than 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]

[ edit ] Assignment operator

The assignment operator ( operator = ) has special properties: see copy assignment and move_assignment for details. To summarize, the canonical "universal assignment operator" implementation is

When there are resources that can be reused in assignment, for example, if the class owns a heap-allocated array, then copy-assignment between arrays of the same size can avoid allocation and deallocation:

[ edit ] Stream extraction and insertion

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 .

[ edit ] Function call operator

When a user-defined class overloads the function call operator, operator ( ) , it becomes a FunctionObject type. Many standard algorithms, from std:: sort to std:: accumulate accept objects of such types to customize behavior. There are no particularly notable canonical forms of operator ( ) , but to illustrate the usage

[ edit ] Increment and decrement

When the postfix increment and decrement appear 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 ) , where the argument is ignored. The postfix increment and decrement operator is usually implemented in terms of the prefix version:

Although canonical form of pre-increment/pre-decrement returns a 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.

[ edit ] Binary arithmetic operators

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:

[ edit ] Relational operators

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 concept). 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 == :

[ edit ] Array subscript operator

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:

If the value type is known to be a built-in 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 l-value c [ i ] = v ; and r-value v = c [ i ] ; usage, operator[] may return a proxy. see for example std::bitset::operator[] .

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 ;

[ edit ] Example

[ edit ] see also.

  • Operator precedence
  • Alternative operator syntax

[ edit ] References

  • ↑ Operator Overloading on StackOverflow C++ FAQ
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 14 August 2015, at 05:37.
  • This page has been accessed 742,100 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Assignment Operators In C++

  • Move Assignment Operator in C++ 11
  • JavaScript Assignment Operators
  • Assignment Operators in Programming
  • Is assignment operator inherited?
  • Solidity - Assignment Operators
  • Augmented Assignment Operators in Python
  • bitset operator[] in C++ STL
  • C++ Assignment Operator Overloading
  • Self assignment check in assignment operator
  • Copy Constructor vs Assignment Operator in C++
  • Operators in C++
  • C++ Arithmetic Operators
  • Bitwise Operators in C++
  • Casting Operators in C++
  • Assignment Operators in C
  • Assignment Operators in Python
  • Compound assignment operators in Java
  • Arithmetic Operators in C
  • Operators in C

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.

Compound Assignment Operators

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++:

  • Addition Assignment Operator ( += )
  • Subtraction Assignment Operator ( -= )
  • Multiplication Assignment Operator ( *= )
  • Division Assignment Operator ( /= )
  • Modulus Assignment Operator ( %= )
  • Bitwise AND Assignment Operator ( &= )
  • Bitwise OR Assignment Operator ( |= )
  • Bitwise XOR Assignment Operator ( ^= )
  • Left Shift Assignment Operator ( <<= )
  • Right Shift Assignment Operator ( >>= )

Lets see each of them in detail.

1. Addition Assignment Operator (+=)

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:

2. Subtraction Assignment Operator (-=)

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.

3. Multiplication Assignment Operator (*=)

In C++, the multiplication assignment operator (*=) is used to update the value of the variable by multiplying it with another value.

4. Division Assignment Operator (/=)

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.

5. Modulus Assignment Operator (%=)

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.

6. Bitwise AND Assignment Operator (&=)

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.

7. Bitwise OR Assignment Operator (|=)

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.

8. Bitwise XOR Assignment Operator (^=)

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.

9. Left Shift Assignment Operator (<<=)

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.

10. Right Shift Assignment Operator (>>=)

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.

Please Login to comment...

Similar reads.

  • Geeks Premier League 2023
  • Geeks Premier League

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Learn C++

21.12 — Overloading the assignment operator

The copy assignment operator (operator=) is used to copy values from one object to another already existing object .

Related content

As of C++11, C++ also supports “Move assignment”. We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

Copy assignment vs Copy constructor

The purpose of the copy constructor and the copy assignment operator are almost equivalent -- both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.

The difference between the copy constructor and the copy assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:

  • If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value).
  • If a new object does not have to be created before the copying can occur, the assignment operator is used.

Overloading the assignment operator

Overloading the copy assignment operator (operator=) is fairly straightforward, with one specific caveat that we’ll get to. The copy assignment operator must be overloaded as a member function.

This prints:

This should all be pretty straightforward by now. Our overloaded operator= returns *this, so that we can chain multiple assignments together:

Issues due to self-assignment

Here’s where things start to get a little more interesting. C++ allows self-assignment:

This will call f1.operator=(f1), and under the simplistic implementation above, all of the members will be assigned to themselves. In this particular example, the self-assignment causes each member to be assigned to itself, which has no overall impact, other than wasting time. In most cases, a self-assignment doesn’t need to do anything at all!

However, in cases where an assignment operator needs to dynamically assign memory, self-assignment can actually be dangerous:

First, run the program as it is. You’ll see that the program prints “Alex” as it should.

Now run the following program:

You’ll probably get garbage output. What happened?

Consider what happens in the overloaded operator= when the implicit object AND the passed in parameter (str) are both variable alex. In this case, m_data is the same as str.m_data. The first thing that happens is that the function checks to see if the implicit object already has a string. If so, it needs to delete it, so we don’t end up with a memory leak. In this case, m_data is allocated, so the function deletes m_data. But because str is the same as *this, the string that we wanted to copy has been deleted and m_data (and str.m_data) are dangling.

Later on, we allocate new memory to m_data (and str.m_data). So when we subsequently copy the data from str.m_data into m_data, we’re copying garbage, because str.m_data was never initialized.

Detecting and handling self-assignment

Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:

By checking if the address of our implicit object is the same as the address of the object being passed in as a parameter, we can have our assignment operator just return immediately without doing any other work.

Because this is just a pointer comparison, it should be fast, and does not require operator== to be overloaded.

When not to handle self-assignment

Typically the self-assignment check is skipped for copy constructors. Because the object being copy constructed is newly created, the only case where the newly created object can be equal to the object being copied is when you try to initialize a newly defined object with itself:

In such cases, your compiler should warn you that c is an uninitialized variable.

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:

If the self-assignment guard did not exist, this function would still operate correctly during a self-assignment (because all of the operations done by the function can handle self-assignment properly).

Because self-assignment is a rare event, some prominent C++ gurus recommend omitting the self-assignment guard even in classes that would benefit from it. We do not recommend this, as we believe it’s a better practice to code defensively and then selectively optimize later.

The copy and swap idiom

A better way to handle self-assignment issues is via what’s called the copy and swap idiom. There’s a great writeup of how this idiom works on Stack Overflow .

The implicit copy assignment operator

Unlike other operators, the compiler will provide an implicit public copy assignment operator for your class if you do not provide a user-defined one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).

Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete keyword:

Note that if your class has const members, the compiler will instead define the implicit operator= as deleted. This is because const members can’t be assigned, so the compiler will assume your class should not be assignable.

If you want a class with const members to be assignable (for all members that aren’t const), you will need to explicitly overload operator= and manually assign each non-const member.

guest

CS107: C++ Programming

Operator overloading.

Operators play an important role in computer programming. By using it, you can change the behavior of an operator based on the types of its arguments.

Operator overloading  (less commonly known as ad-hoc polymorphism) is a specific case of polymorphism (part of the OO nature of the language) in which some or all operators like  + ,  =  or  ==  are treated as polymorphic functions and as such have different behaviors depending on the types of its arguments. Operator overloading is usually only syntactic sugar. It can easily be emulated using function calls.

Consider this operation:

Using operator overloading permits a more concise way of writing it, like this:

(Assuming the  *  operator has higher precedence than  + .)

Operator overloading can provide more than an aesthetic benefit, since the language allows operators to be invoked implicitly in some circumstances. Problems, and critics, to the use of operator overloading arise because it allows programmers to give operators completely free functionality, without an imposition of coherency that permits to consistently satisfy user/reader expectations. Usage of the  <<  operator is an example of this problem.

Will return twice the value of  a  if  a  is an integer variable, but if  a  is an output stream instead this will write "1" to it. Because operator overloading allows the programmer to change the usual semantics of an operator, it is usually considered good practice to use operator overloading with care.

To overload an operator is to provide it with a new meaning for user-defined types. This is done in the same fashion as defining a function. The basic syntax follows (where @ represents a valid operator):

Not all operators may be overloaded, new operators cannot be created, and the precedence, associativity or arity of operators cannot be changed (for example   ! cannot be overloaded as a binary operator). Most operators may be overloaded as either a member function or non-member function, some, however, must be defined as member functions. Operators should only be overloaded where their use would be natural and unambiguous, and they should perform as expected. For example, overloading + to add two complex numbers is a good use, whereas overloading * to push an object onto a vector would not be considered good style.

A simple Message Header

Operators as member functions

Aside from the operators which must be members, operators may be overloaded as member or non-member functions. The choice of whether or not to overload as a member is up to the programmer. Operators are generally overloaded as members when they:

  • change the left-hand operand, or
  • require direct access to the non-public parts of an object.

When an operator is defined as a member, the number of explicit parameters is reduced by one, as the calling object is implicitly supplied as an operand. Thus, binary operators take one explicit parameter and unary operators none. In the case of binary operators, the left hand operand is the calling object, and no type coercion will be done upon it. This is in contrast to non-member operators, where the left hand operand may be coerced.

Overloadable operators

Arithmetic operators.

  • +  (addition)
  • -  (subtraction)
  • *  (multiplication)
  • /  (division)
  • %  (modulus)

As binary operators, these involve two arguments which do not have to be the same type. These operators may be defined as member or non-member functions. An example illustrating overloading for the addition of a 2D mathematical vector type follows.

It is good style to only overload these operators to perform their customary arithmetic operation. Because operator has been overloaded as member function, it can access private fields.

Bitwise operators

  • ^  (XOR)
  • |  (OR)
  • &  (AND)
  • ~  (complement)
  • <<  (shift left, insertion to stream)
  • >>  (shift right, extraction from stream)

All of the bitwise operators are binary, except complement, which is unary. It should be noted that these operators have a lower precedence than the arithmetic operators, so if ^ were to be overloaded for exponentiation, x ^ y + z may not work as intended. Of special mention are the shift operators, << and >> . These have been overloaded in the standard library for interaction with streams. When overloading these operators to work with streams the rules below should be followed:

  • overload << and >> as friends (so that it can access the private variables with the stream be passed in by references
  • (input/output modifies the stream, and copying is not allowed)
  • the operator should return a reference to the stream it receives (to allow chaining, cout << 3 << 4 << 5 )

Assignment operator

The assignment operator,  = ,  must be a member function , and is given default behavior for user-defined classes by the compiler, performing an assignment of every member using its assignment operator. This behavior is generally acceptable for simple classes which only contain variables. However, where a class contains references or pointers to outside resources, the assignment operator should be overloaded (as general rule, whenever a destructor and copy constructor are needed so is the assignment operator), otherwise, for example, two strings would share the same buffer and changing one would change the other.

In this case, an assignment operator should perform two duties:

  • clean up the old contents of the object
  • copy the resources of the other object

For classes which contain raw pointers, before doing the assignment, the assignment operator should check for self-assignment, which generally will not work (as when the old contents of the object are erased, they cannot be copied to refill the object). Self assignment is generally a sign of a coding error, and thus for classes without raw pointers, this check is often omitted, as while the action is wasteful of cpu cycles, it has no other effect on the code.

Another common use of overloading the assignment operator is to declare the overload in the private part of the class and not define it. Thus any code which attempts to do an assignment will fail on two accounts, first by referencing a private member function and second fail to link by not having a valid definition. This is done for classes where copying is to be prevented, and generally done with the addition of a privately declared copy constructor

Relational operators

  • ==  (equality)
  • !=  (inequality)
  • >  (greater-than)
  • <  (less-than)
  • >=  (greater-than-or-equal-to)
  • <=  (less-than-or-equal-to)

All relational operators are binary, and should return either true or false. Generally, all six operators can be based off a comparison function, or each other, although this is never done automatically (e.g. overloading > will not automatically overload < to give the opposite). There are, however, some templates defined in the header <utility> ; if this header is included, then it suffices to just overload operator == and operator < , and the other operators will be provided by the STL.

Logical operators

  • !  (NOT)
  • &&  (AND)
  • ||  (OR)

The logical operators AND are used when evaluating two expressions to obtain a single relational result.The operator corresponds to the boolean logical operation AND, which yields true if operands are true, and false otherwise.The following panel shows the result of operator evaluating the expression.

The  ! operator is unary, && and || are binary. It should be noted that in normal use, && and || have "short-circuit" behavior, where the right operand may not be evaluated, depending on the left operand. When overloaded, these operators get function call precedence, and this short circuit behavior is lost. It is best to leave these operators alone.

If the result of Function1 () is false, then Function2 () is not called.

Both Function3 () and Function4 () will be called no matter what the result of the call is to Function3 () . This is a waste of CPU processing, and worse, it could have surprising unintended consequences compared to the expected "short-circuit" behavior of the default operators. Consider:

Compound assignment operators

  • +=  (addition-assignment)
  • -=  (subtraction-assignment)
  • *=  (multiplication-assignment)
  • /=  (division-assignment)
  • %=  (modulus-assignment)
  • &=  (AND-assignment)
  • |=  (OR-assignment)
  • ^=  (XOR-assignment)
  • <<=  (shift-left-assignment)
  • >>=  (shift-right-assignment)

Compound assignment operators should be overloaded as member functions, as they change the left-hand operand. Like all other operators (except basic assignment), compound assignment operators must be explicitly defined, they will not be automatically (e.g. overloading = and + will not automatically overload += ). A compound assignment operator should work as expected: A @= B should be equivalent to A = A @ B . An example of += for a two-dimensional mathematical vector type follows.

Increment and decrement operators

  • ++  (increment)
  • --  (decrement)

Increment and decrement have two forms, prefix ( ++ i ) and postfix ( i ++ ). To differentiate, the postfix version takes a dummy integer. Increment and decrement operators are most often member functions, as they generally need access to the private member data in the class. The prefix version in general should return a reference to the changed object. The postfix version should just return a copy of the original value. In a perfect world, A += 1 , A = A + 1 , A ++ , ++ A should all leave A with the same value.

Often one operator is defined in terms of the other for ease in maintenance, especially if the function call is complex.

Subscript operator

The subscript operator,  [ ] , is a binary operator which  must be a member function  (hence it takes only one explicit parameter, the index). The subscript operator is not limited to taking an integral index. For instance, the index for the subscript operator for the std::map template is the same as the type of the key, so it may be a string etc. The subscript operator is generally overloaded twice; as a non-constant function (for when elements are altered), and as a constant function (for when elements are only accessed).

Function call operator

The function call operator,  ( ) , is generally overloaded to create objects which behave like functions, or for classes that have a primary operation. The function call operator must be a member function, but has no other restrictions - it may be overloaded with any number of parameters of any type, and may return any type. A class may also have several definitions for the function call operator.

Address of, Reference, and Pointer operators

These three operators, operator &() , operator *() and operator ->() can be overloaded. In general these operators are only overloaded for smart pointers, or classes which attempt to mimic the behavior of a raw pointer. The pointer operator, operator->() has the additional requirement that the result of the call to that operator, must return a pointer, or a class with an overloaded operator ->(). In general A == *& A should be true.

Note that overloading operator& invokes undefined behavior:

These are extremely simplified examples designed to show how the operators can be overloaded and not the full details of a SmartPointer or SmartReference class. In general you won't want to overload all three of these operators in the same class.

Comma operator

The comma operator ,()  ,  can be overloaded. The language comma operator has left to right precedence, the operator ,() has function call precedence, so be aware that overloading the comma operator has many pitfalls.

For non overloaded comma operator, the order of execution will be Function1(), Function2(); With the overloaded comma operator, the compiler can call either Function1(), or Function2() first.

Member Reference operators

The two member access operators, operator ->() and operator ->*() can be overloaded. The most common use of overloading these operators is with defining expression template classes, which is not a common programming technique. Clearly by overloading these operators you can create some very unmaintainable code so overload these operators only with great care.

When the -> operator is applied to a pointer value of type (T *), the language dereferences the pointer and applies the . member access operator (so x -> m is equivalent to (* x ). m ). However, when the -> operator is applied to a class instance, it is called as a unary postfix operator; it is expected to return a value to which the -> operator can again be applied. Typically, this will be a value of type (T *), as in the example under Address of, Reference, and Pointer operators above, but can also be a class instance with operator ->() defined; the language will call operator ->() as many times as necessary until it arrives at a value of type (T *).

Memory management operators

  • new  (allocate memory for object)
  • new [ ]  (allocate memory for array)
  • delete  (deallocate memory for object)
  • delete [ ]  (deallocate memory for array)

The memory management operators can be overloaded to customize allocation and deallocation (e.g. to insert pertinent memory headers). They should behave as expected,  new  should return a pointer to a newly allocated object on the heap,  delete  should deallocate memory, ignoring a NULL argument. To overload  new , several rules must be followed:

  • new  must be a member function
  • the return type must be  void *
  • the first explicit parameter must be a  size_t  value

To overload  delete  there are also conditions:

  • delete  must be a member function (and cannot be virtual)
  • the return type must be  void
  • void *, size_t

Conversion operators

Conversion operators enable objects of a class to be either implicitly (coercion) or explicitly (casting) converted to another type. Conversion operators must be member functions, and should not change the object which is being converted, so should be flagged as constant functions. The basic syntax of a conversion operator declaration, and declaration for an int-conversion operator follows.

Notice that the function is declared without a return-type, which can easily be inferred from the type of conversion. Including the return type in the function header for a conversion operator is a syntax error.

Operators which cannot be overloaded

  • ?:  (conditional)
  • .  (member selection)
  • .*  (member selection with pointer-to-member)
  • ::  (scope resolution)
  • sizeof  (object size information)
  • typeid  (object type information)
  • static_cast (casting operator)
  • const_cast (casting operator)
  • reinterpret_cast (casting operator)
  • dynamic_cast (casting operator)

To understand the reasons why the language doesn't permit these operators to be overloaded, read "Why can't I overload dot, ::,  sizeof , etc.?" at the Bjarne Stroustrup's C++ Style and Technique FAQ ( http://www.stroustrup.com/bs_faq2.html#overload-dot ).

Creative Commons License

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Assignment operators (C# reference)

  • 11 contributors

The assignment operator = assigns the value of its right-hand operand to a variable, a property , or an indexer element given by its left-hand operand. The result of an assignment expression is the value assigned to the left-hand operand. The type of the right-hand operand must be the same as the type of the left-hand operand or implicitly convertible to it.

The assignment operator = is right-associative, that is, an expression of the form

is evaluated as

The following example demonstrates the usage of the assignment operator with a local variable, a property, and an indexer element as its left-hand operand:

The left-hand operand of an assignment receives the value of the right-hand operand. When the operands are of value types , assignment copies the contents of the right-hand operand. When the operands are of reference types , assignment copies the reference to the object.

This is called value assignment : the value is assigned.

ref assignment

Ref assignment = ref makes its left-hand operand an alias to the right-hand operand, as the following example demonstrates:

In the preceding example, the local reference variable arrayElement is initialized as an alias to the first array element. Then, it's ref reassigned to refer to the last array element. As it's an alias, when you update its value with an ordinary assignment operator = , the corresponding array element is also updated.

The left-hand operand of ref assignment can be a local reference variable , a ref field , and a ref , out , or in method parameter. Both operands must be of the same type.

Compound assignment

For a binary operator op , a compound assignment expression of the form

is equivalent to

except that x is only evaluated once.

Compound assignment is supported by arithmetic , Boolean logical , and bitwise logical and shift operators.

Null-coalescing assignment

You can use the null-coalescing assignment operator ??= to assign the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null . For more information, see the ?? and ??= operators article.

Operator overloadability

A user-defined type can't overload the assignment operator. However, a user-defined type can define an implicit conversion to another type. That way, the value of a user-defined type can be assigned to a variable, a property, or an indexer element of another type. For more information, see User-defined conversion operators .

A user-defined type can't explicitly overload a compound assignment operator. However, if a user-defined type overloads a binary operator op , the op= operator, if it exists, is also implicitly overloaded.

C# language specification

For more information, see the Assignment operators section of the C# language specification .

  • C# operators and expressions
  • ref keyword
  • Use compound assignment (style rules IDE0054 and IDE0074)

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

IMAGES

  1. How to work with operator overloading in C#

    overloading compound assignment operator

  2. Overloading Assignment Operator

    overloading compound assignment operator

  3. 025 Compound assignment operators (Welcome to the course C programming)

    overloading compound assignment operator

  4. PPT

    overloading compound assignment operator

  5. Overloading assignment operator in C++

    overloading compound assignment operator

  6. Matrix addition using operator overloading in c

    overloading compound assignment operator

VIDEO

  1. Relational Operator Overloading in C++ [Hindi]

  2. Operator Overloading In Python #assignment #cybersecurity #svce

  3. Operator Overloading Part 2

  4. 9

  5. Compound Assignment Operators in C language

  6. Compound Assignment Operators, Type Safety

COMMENTS

  1. c++

    In general, the addition and assignment will do the same thing as the compound assignment, but this is not always the case. In general, when overloading the arithmetic operators ( +, - etc.) you should do them with their associated compound assignments as well ( +=, -= etc.). See the "Binary arithmetic operators" on cppreference for some ...

  2. Assignment operators

    For all other compound assignment operators, the type of target-expr must be an arithmetic type. 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:

  3. Overloading compound assignment operators in C++

    foo operator+(foo a, const foo &b) { // First argument passed by value, second by reference. return a += b; } Making the compound operators class members and the plain operators freestanding is a common style suggestion; it allows the first argument to be of a different type as long as it can be converted to a foo: foo b; foo a = 1 + b; (All ...

  4. C++ Programming/Operators/Operator Overloading

    Compound assignment operators should be overloaded as member functions, as they change the left-hand operand. Like all other operators (except basic assignment), compound assignment operators must be explicitly defined, they will not be automatically (e.g. overloading = and + will not automatically overload +=).

  5. C++ Operator Overloading Guidelines

    This is called operator overloading. You can implement C++ operator overloads by providing special member-functions on your classes that follow a particular naming convention. For example, to ... Implement the compound assignment operators from scratch, and then define the binary arithmetic operators in terms of the corresponding compound ...

  6. C++ Assignment Operator Overloading

    The assignment operator,"=", is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types. Assignment operator overloading is binary operator overloading. Overloading assignment operator in C++ copies all values of one object to another object.

  7. modern C++ by Xeverous

    05 - compound assignment. Compound assignment operators can be defined both as free functions and as member functions. Member functions are preferred because their implementation is simpler and since the operation has no symmetry (a += b is not the same as b += a for non-numeric abstractions, e.g. strings) there are no problems with inconsistent implicit convertion.

  8. PDF Operator Overloading

    Overloading Compound Assignment Operators The compound assignment operators are operators of the form op= (for example, += and *=) that update an object's value but do not overwrite it. The basic prototype for a compound assignment operator is MyClass& operator += (ParameterType param) When writing compound assignment operators, you still need ...

  9. Assignment operators

    Compound assignment. The compound assignment operators are shown in the Assignment operators table. These operators have the form e1 op= e2, where e1 is a non-const modifiable l-value and e2 is: an arithmetic type. a pointer, if op is + or -a type for which there exists a matching operator *op*= overload for the type of e1

  10. operator overloading

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

  11. Assignment Operators In C++

    Compound Assignment Operators. 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. ... 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 ...

  12. 21.12

    21.12 — Overloading the assignment operator. Alex November 27, 2023. 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 .

  13. Overloading compound assignments: +=, etc.

    Overloading compound assignments: +=, etc. The compound assignment ``add and assign'' a += b; is equivalent to a = a + b; Similarly, C++ provides operators for the compound assignments -=, *=, and /=. The function names corresponding to them are operator+=, etc. For operations between pairs of vectors, the meanings of ``add and assign'' and ...

  14. 9- Overloading Compound Assignment Operators

    10- Overloading the Assignment Operator (5:12) 11- Overloading Unary Operators (5:15) 12- Overloading the Subscript Operator (6:05) ... 9- Overloading Compound Assignment Operators Lesson content locked If you're already enrolled, you'll need to login.

  15. CS107: Operator Overloading

    Compound assignment operators should be overloaded as member functions, as they change the left-hand operand. Like all other operators (except basic assignment), compound assignment operators must be explicitly defined, they will not be automatically (e.g. overloading = and + will not automatically overload += ).

  16. operator overloading

    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), ... Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms ...

  17. Compound assignment and add operator overloading

    This will lead to cosider the rule of three: If you need any one of desgtructor, copy-constructor or assignment operator, you most likely need all three. +1 for clear examples. You need to swap the indices in the 2nd for loop in each function, however: you need String[i+Size] and rhs.String[i] in both cases.

  18. Assignment operators

    A user-defined type can't explicitly overload a compound assignment operator. However, if a user-defined type overloads a binary operator op, the op= operator, if it exists, is also implicitly overloaded. C# language specification. For more information, see the Assignment operators section of the C# language specification. See also. C# ...

  19. Arabic Compound Numerals: New Insights on Case, Agreement, and ...

    This paper examines the syntax of additive compound numerals in Modern Standard Arabic (MSA), uncovering their unique properties related to number morphology, definiteness, and Case assignment within numeral-noun constructions. These properties necessitate a constituency analysis which reveals that compound numerals have the structure of copulative compounds in MSA, and they are phrases, not ...

  20. Operator overloading for compound assignment operators on enums

    3. There's a lot of information, examples etc. for operator overloading of all kinds on the web. But I can't for the life of me find an example on how to do this for a simple enum and, say, the |= or the += operators. For a bitwise or the implementation is this: inline MyEnum operator | (MyEnum a, MyEnum b) return (MyEnum)((int)a | (int)b); All ...

  21. Simple way to overload compound assignment operator in C#?

    You can't explicitly overload the compound assignment operators. You can however overload the main operator and the compiler expands it. x += 1 is purely syntactic sugar for x = x + 1 and the latter is what it will be translated to. If you overload the + operator it will be called. MSDN Operator Overloading Tutorial. return new Complex(c1.real ...