C++ Operators
The following Table contains C++ operators organized by category.
|
| Category | Description | Symbol |
| Additive | Addition Subtraction | + – |
| Assignment | Addition Assignment Assignment Bitwise AND Assignment Bitwise exclusive OR Assignment Bitwise inclusive OR Assignment Division Assignment Left shift assignment Modulus Assignment Multiplication Assignment Right shift assignment Subtraction Assignment | += = &= ^= |= /= <<= %= *= >>= –= |
| Bitwise | Bitwise AND Bitwise exclusive OR Bitwise inclusive OR | & ^ | |
| Logical | Logical AND Logical OR | && || |
| Multiplicative | Division Modulus Multiplication | / % * |
| Postfix | Cast Function call Member access Postfix decrement Postfix increment Subscript | () ( ) . and –> –– ++ [ ] |
| Relational and Equality | Equality Greater than or equal to Greater than Less than or equal to Less than Not equal | == >= > <= < != |
| Shift | Left shift Right shift | << >> |
| Unary | Address-of delete Indirection Logical Negation new One's Complement Prefix decrement Prefix increment sizeof Unary Plus Operator Unary Negation Operator | & none * ! none ~ –– ++ none + - |
| Miscellaneous | Comma Conditional Pointer-to-member Reference Scope resolution | , ? : .* or –>* & :: |
|
Table 1 | ||
Operator Precedence and Associativity
The C++ language includes all C operators and adds several new operators. Operators specify an evaluation to be performed on one of the following:
One operand (unary operator).
Two operands (binary operator).
Three operands (ternary operator).
Operators follow a strict precedence, which defines the evaluation order of expressions containing these operators. Operators associate with either the expression on their left or the expression on their right; this is called "associativity." The following table shows the precedence and associativity of C++ operators (from highest to lowest precedence). Operators in the same segment of the table have equal precedence and are evaluated in the given order in an expression unless explicitly forced by parentheses.
C++ Operator Precedence and Associativity Table
| Operator (arranged in one line!) | Name or Meaning | Associativity |
| :: | Scope resolution | None |
| ., –>, [ ], ( ), ( ), ++, ––, typeid( ), const_cast, dynamic_cast, reinterpret_cast, static_cast | Member selection (object), Member selection (pointer), Array subscript, Function call member initialization, Postfix increment, Postfix decrement, type name, Type cast (conversion), Type cast (conversion), Type cast (conversion), Type cast (conversion). | Left to right. |
| sizeof, ++, ––, ~, !, –, +, &, *, new, delete, () | Size of object or type, Prefix increment, Prefix decrement, One's complement, Logical not, Unary minus, Unary plus, Address-of, Indirection, Create object, Destroy object, Cast | Right to left. |
| .*, –>* | Pointer-to-member (objects), Pointer-to-member (pointers) | Left to right |
| *, /, % | Multiplication, Division, Modulus | Left to right |
| +, – | Addition, Subtraction | Left to right |
| <<, >> | Left shift Right shift | Left to right |
| <, >, <=, >= | Less than, Greater than, Less than or equal to, Greater than or equal to | Left to right |
| ==, != | Equality, Inequality | Left to right |
| & | Bitwise AND | Left to right |
| ^ | Bitwise exclusive OR | Left to right |
| | | Bitwise inclusive OR | Left to right |
| && | Logical AND | Left to right |
| || | Logical OR | Left to right |
| e1 ? e2 : e3 | Conditional | Right to left |
| =*, =/, =%, =+, =–, =<<, =>>, =&, =|, =^, = | Assignment Multiplication, assignment Division, assignment Modulus, assignment Addition, assignment Subtraction, assignment Left-shift, assignment Right-shift, assignment Bitwise AND, assignment Bitwise inclusive OR, assignment Bitwise exclusive OR, assignment | Right to left |
| throw expr | throw expression | Right to left |
| , | Comma | Left to right |
|
Table 2 | ||
Operator Overloading
The operator keyword declares a function specifying what operator-symbol means when applied to instances of a class. This gives the operator more than one meaning, or "overloads" it. The compiler distinguishes between the different meanings of an operator by examining the types of its operands.
type operator operator-symbol(parameter-list)
Example:
static bool operator==(const Operation^, const Operation^);
You can redefine the function of most built-in operators globally or on a class-by-class basis. Overloaded operators are implemented as functions. The name of an overloaded operator is operatorx, where x is the operator as it appears in the following table. For example, to overload the addition operator, you define a function called operator+. Similarly, to overload the addition/assignment operator, +=, define a function called operator+=.
Overloadable Operators
| Operator | Name | Type |
| , | Comma | Binary |
| ! | Logical NOT | Unary |
| != | Inequality | Binary |
| % | Modulus | Binary |
| %= | Modulus assignment | Binary |
| & | Bitwise AND | Binary |
| & | Address-of | Unary |
| && | Logical AND | Binary |
| &= | Bitwise AND assignment | Binary |
| ( ) | Function call | — |
| * | Multiplication | Binary |
| * | Pointer dereference | Unary |
| *= | Multiplication assignment | Binary |
| + | Addition | Binary |
| + | Unary Plus | Unary |
| ++ | Increment1 | Unary |
| += | Addition assignment | Binary |
| – | Subtraction | Binary |
| – | Unary negation | Unary |
| –– | Decrement1 | Unary |
| –= | Subtraction assignment | Binary |
| –> | Member selection | Binary |
| –>* | Pointer-to-member selection | Binary |
| / | Division | Binary |
| /= | Division assignment | Binary |
| < | Less than | Binary |
| << | Left shift | Binary |
| <<= | Left shift assignment | Binary |
| <= | Less than or equal to | Binary |
| = | Assignment | Binary |
| == | Equality | Binary |
| > | Greater than | Binary |
| >= | Greater than or equal to | Binary |
| >> | Right shift | Binary |
| >>= | Right shift assignment | Binary |
| [ ] | Array subscript | — |
| ^ | Exclusive OR | Binary |
| ^= | Exclusive OR assignment | Binary |
| | | Bitwise inclusive OR | Binary |
| |= | Bitwise inclusive OR assignment | Binary |
| || | Logical OR | Binary |
| ~ | One's complement | Unary |
| delete | Delete | — |
| new | New | — |
| conversion operators | conversion operators | Unary |
|
Table 3 | ||
Note: Two versions of the unary increment and decrement operators exist: preincrement and postincrement.
Non Overloadable Operators
The operators shown in the following table cannot be overloaded. The table includes the preprocessor symbols # and ##.
| Operator | Name |
| . | Member selection |
| .* | Pointer-to-member selection |
| :: | Scope resolution |
| ? : | Conditional |
| # | Preprocessor convert to string |
| ## | Preprocessor concatenate |
|
Table 4 | |
Although overloaded operators are usually called implicitly by the compiler when they are encountered in code, they can be invoked explicitly the same way as any member or nonmember function is called:
Point pt;
pt.operator+(3); // Call addition operator to add 3 to pt.
Example
The following traditional C++ code example overloads the + operator to add two complex numbers and returns the result.
// traditional C++ operator overloading
// compile with: /clr
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
struct Complex
{
Complex(double r, double i) : re(r), im(i) {}
// Overloaded the addition...
Complex operator+(Complex &other);
void Display()
{
cout<<"Real part = "<<re<<", "<<"Imaginary part = "<<im<< endl;
}
private:
double re, im;
};
// Operator overloaded using a member function
Complex Complex::operator+(Complex &other)
{
return Complex(re + other.re, im + other.im);
}
int main()
{
Complex a = Complex(1.2, 3.4);
cout<<"a: ";
a.Display();
Complex b = Complex(5.6, 7.8);
cout<<"b: ";
b.Display();
Complex c = Complex(0.0, 0.0);
cout<<"c: ";
c.Display();
cout<<endl;
c = a + b;
cout<<"c = a + b: ";
c.Display();
}
Output:

Overloaded Operators
Operator overloading has changed significantly from Managed Extensions for C++ to Visual C++ 2005. Perhaps the most striking aspect of Managed Extensions is its support for operator overloading or rather, its effective absence. Within the declaration of a reference type, for example, rather than using the native operator+ syntax, one has to explicitly write out the underlying internal name of the operator, in this case, op_Addition. More onerous, however, is the fact that the invocation of an operator has to be explicitly invoked through that name, thus precluding the two primary benefits of operator overloading:
The intuitive syntax, and
The ability to intermix new types with existing types.
For example:
// operator overloading
// Compile with /clr:OldSyntax
#include "stdafx.h"
using namespace System;
public __gc __sealed class Operation
{
public:
// ...
Operation(double x, double y, double z);
static bool op_Equality(const Operation*, const Operation*);
static Operation* op_Division(const Operation*, double);
static Operation* op_Addition(const Operation*, const Operation*);
static Operation* op_Subtraction(const Operation*, const Operation*);
// ...
};
int main()
{
Operation *pa = new Operation(0.231, 2.4745, 0.023);
Operation *pb = new Operation(1.475, 4.8916, -1.23);
Operation *pc1 = Operation::op_Addition(pa, pb);
Operation *pc2 = Operation::op_Subtraction(pa, pc1);
Operation *pc3 = Operation::op_Division(pc1, pc2->x);
if (Operation::op_Equality(pc1, pc2))
// ;
// ...
}
In the new syntax, the usual expectations of a native C++ programmer are restored, both in the declaration and use of the static operators. Here is the Vector class translated into the new syntax:
// operator overloading
// Compile with /clr
#include "stdafx.h"
using namespace System;
public ref class Operation sealed
{
public:
// ...
Operation(double x, double y, double z);
static bool operator ==(const Operation^, const Operation^);
static Operation^ operator /(const Operation^, double);
static Operation^ operator +(const Operation^, const Operation^);
static Operation^ operator -(const Operation^, const Operation^);
// ...
};
int main()
{
Operation^ pa = gcnew Operation(0.231, 2.4745, 0.023);
Operation^ pb = gcnew Operation(1.475,4.8916,-1.23);
Operation^ pc1 = pa + pb;
Operation^ pc2 = pa - pc1;
Operation^ pc3 = pc1 / pc2->x;
if (pc1 == pc2)
// ;
// ...
}
The following is another Managed Extension of C++ example.
// Operator overloading, Managed Extension for C++
// Compile with /clr:OldSyntax
#include "stdafx.h"
using namespace System;
// The Dbl struct definition
__value struct Dbl
{
double val;
// creation or assignment time
double hr, min, sec;
public:
Dbl(double v)
{
val = v;
// Create new date and time fields
DateTime dt = DateTime::get_Now();
hr = dt.get_Hour();
min = dt.get_Minute();
sec = dt.get_Second();
}
double getVal() { return val; }
// The addition operator for the Dbl struct
// lhs - left hand side, rhs - right hand side
static Dbl op_Addition(Dbl lhs, Dbl rhs)
{
Dbl result(lhs.val + rhs.val);
return result;
}
// Adding a Dbl and an int
static Dbl op_Addition(Dbl lhs, int rhs)
{
Dbl result(lhs.val + rhs);
return result;
}
// Adding an int and a Dbl
static Dbl op_Addition(int lhs, Dbl rhs)
{
Dbl result(lhs + rhs.val);
return result;
}
// The equality operator for the Dbl struct
static bool op_Equality(Dbl lhs, Dbl rhs)
{
return lhs.val == rhs.val;
}
// The inequality operator for the Dbl struct
static bool op_Inequality(Dbl lhs, Dbl rhs)
{
return !(lhs == rhs); // calls op_Equality()
}
// The equality operator for the Dbl struct
bool Equals(Object* pOther)
{
Dbl* s = dynamic_cast<Dbl*>(pOther);
if (s == 0) return false;
return s->val == val;
}
// The assignment operator for the Dbl struct
static Dbl op_Assign(Dbl& lhs, const Dbl& rhs)
{
// Copy over the value
lhs.val = rhs.val;
// Create new date and time fields
DateTime dt = DateTime::get_Now();
lhs.hr = dt.get_Hour();
lhs.min = dt.get_Minute();
lhs.sec = dt.get_Second();
return lhs;
}
// The increment operator for the Dbl struct
static Dbl op_Increment(Dbl d)
{
d.val += 1;
return d;
}
};
int main()
{
Dbl d1(10.0);
Dbl d2(20.0);
Dbl d3(0.0);
// Add two Dbl’s
d3 = d1 + d2;
Console::Write("Value of d3 is ");
Console::WriteLine(d3.getVal());
// Add a Dbl and an int
d3 = d1 + 5;
Console::Write("Value of d3 is now ");
Console::WriteLine(d3.getVal());
// Add an int and a Dbl
d3 = 5 + d2;
Console::Write("Value of d3 is now ");
Console::WriteLine(d3.getVal());
if (d1 == d2)
Console::WriteLine("d1 and d2 are equal");
else
Console::WriteLine("d1 and d2 are not equal");
if (d1.Equals(__box(d2)))
Console::WriteLine("d1 and d2 are equal");
else
Console::WriteLine("d1 and d2 are not equal");
// Create two objects
Dbl one(0.0);
Dbl two(10.0);
// Sleep for five seconds
Console::WriteLine("Wait... ");
System::Threading::Thread::Sleep(5000);
// Do an assignment
one = two;
// Create a Dbl, and increment it
Dbl d5(1.0);
Console::Write("Initial value of d5 is ");
Console::WriteLine(d5.getVal());
// Increment it
d5++;
Console::Write("Value of d5 is now ");
Console::WriteLine(d5.getVal());
return 0;
}
Output:
![]() |
The scale down version of the previous program example is shown below.
// Operator overloading
// Compile with /clr:OldSyntax
#include "stdafx.h"
using namespace System;
// The Dbl struct definition
__value struct Dbl
{
double val;
public:
Dbl(double v)
{
Console::WriteLine("In Dbl()...");
val = v;
}
double getVal()
{
return val;
}
// The addition operator for the Dbl struct
// lhs - left hand side, rhs - right hand side
static Dbl op_Addition(Dbl lhs, Dbl rhs)
{
Console::WriteLine("In op_Addition()...");
Dbl result(lhs.val + rhs.val);
return result;
}
};
int main()
{
Dbl d1(10.0);
Dbl d2(20.0);
Dbl d3(0.0);
d3 = d1 + d2;
Console::WriteLine("Go to getVal()...");
Console::Write("Value of d3 is ");
Console::WriteLine(d3.getVal());
return 0;
}
Output:

// Operator overloading, new C++
// Compile with /clr
#include "stdafx.h"
using namespace System;
// The Dbl struct definition
value struct Dbl
{
double val;
// creation or assignment time
double hr, min, sec;
public:
Dbl(double v)
{
val = v;
// Create new date and time fields
DateTime dt = DateTime::Now;
hr = dt.Hour;
min = dt.Minute;
sec = dt.Second;
}
double getVal() { return val; }
// The addition operator for the Dbl struct
// lhs - left hand side, rhs - right hand side
static Dbl operator+(Dbl lhs, Dbl rhs)
{
Dbl result(lhs.val + rhs.val);
return result;
}
// Adding a Dbl and an int
static Dbl operator+(Dbl lhs, int rhs)
{
Dbl result(lhs.val + rhs);
return result;
}
// Adding an int and a Dbl
static Dbl operator+(int lhs, Dbl rhs)
{
Dbl result(lhs + rhs.val);
return result;
}
// The equality operator for the Dbl struct
static bool operator==(Dbl lhs, Dbl rhs)
{
return lhs.val == rhs.val;
}
// The inequality operator for the Dbl struct
static bool operator!=(Dbl lhs, Dbl rhs)
{
return !(lhs == rhs); // calls op_Equality()
}
// The equality operator for the Dbl struct
virtual bool Equals(Object^ pOther) override
{
Dbl^ s = dynamic_cast<Dbl^>(pOther);
if (s == nullptr) return false;
return s->val == val;
}
// The assignment operator for the Dbl struct
// cannot use the operator=( , )
static Dbl op_Assign(Dbl& lhs, const Dbl& rhs)
{
// Copy over the value
lhs.val = rhs.val;
// Create new date and time fields
DateTime dt = DateTime::Now;
lhs.hr = dt.Hour;
lhs.min = dt.Minute;
lhs.sec = dt.Second;
return lhs;
}
// The increment operator for the Dbl struct
static Dbl operator++(Dbl d)
{
d.val += 1;
return d;
}
};
int main()
{
Dbl d1(10.0);
Dbl d2(20.0);
Dbl d3(0.0);
// Add two Dbl’s
d3 = d1 + d2;
Console::Write("Value of d3 is ");
Console::WriteLine(d3.getVal());
// Add a Dbl and an int
d3 = d1 + 5;
Console::Write("Value of d3 is now ");
Console::WriteLine(d3.getVal());
// Add an int and a Dbl
d3 = 5 + d2;
Console::Write("Value of d3 is now ");
Console::WriteLine(d3.getVal());
if (d1 == d2)
Console::WriteLine("d1 and d2 are equal");
else
Console::WriteLine("d1 and d2 are not equal");
if (d1.Equals((Object^)d2))
Console::WriteLine("d1 and d2 are equal");
else
Console::WriteLine("d1 and d2 are not equal");
// Create two objects
Dbl one(0.0);
Dbl two(10.0);
// Sleep for five seconds
Console::WriteLine("Wait... ");
System::Threading::Thread::Sleep(5000);
// Do an assignment
one = two;
// Create a Dbl, and increment it
Dbl d5(1.0);
Console::Write("Initial value of d5 is ");
Console::WriteLine(d5.getVal());
// Increment it
d5++;
Console::Write("Value of d5 is now ");
Console::WriteLine(d5.getVal());
return 0;
}
Output:
