c++ Operators

Operators
C/C++ has the following seven arithmetic operators:
Operator
Action
Subtraction, unary minus
+
Addition
*
Multiplication
/
Division
%
Modulus
– –
Decrement
+ +
Increment

The +, –, *, and / operators work in the expected fashion. The % operator returns the remainder of an integer division. The increment and decrement operators increase or decrease the operand by one.
These operators have the following order of precedence:
Precedence
Operators
Highest
++  – –  – (unary minus)
*  /  %
Lowest
+  –
Operators on the same precedence level are evaluated left to right.


Relational and Logical Operators

The relational and logical operators are used to produce Boolean (true/false) results and are often used together. In C/C++, any nonzero number evaluates as true. Zero is false. In C++, the outcome of the relational and logical operators is of type bool. In C, the outcome is a zero or nonzero integer. The relational operators are listed here:
Operator
Meaning
>
Greater than
>=
Greater than or equal
<
Less than
<=
Less than or equal
==
Equal
!=
Not equal

The logical operators are shown here:
Operator
Meaning
&&
AND
||
OR
!
NOT

The relational operators compare two values, producing a Boolean result. The logical operators connect two

Boolean values or, in the case of !, reverse a value. The precedence of these operators is shown here:
Precedence
Operators
Highest
!
>  >=  <  <=
==  !=
&&
Lowest
||

As an example, the following if statement evaluates to true and prints the line x is less than 10:
x = 9;
if(x < 10) cout << "x is less than 10";
 
However, in the following example, no message is displayed because both operands associated with &&
must be true for the outcome to be true:
x = 9;
y = 9;
if(x < 10 && y > 10) 
  cout << "This will not print.";
 

The Bitwise Operators

C and C++ provide operators that act upon the actual bits that comprise a value. The bitwise operators can be used only on integral types. The bitwise operators are as follows:
Operator
Meaning
&
AND
|
OR
^
XOR
~
One’s complement
>>
Right shift
<<
Left shift

&, |, and ^

The truth tables for &, |, and ^ are as follows:
p
q
p & q
p | q
p ^ q
0
0
0
0
0
0
1
0
1
1
1
1
1
1
0
1
0
0
1
1

These rules are applied to each bit in each operand when the bitwise AND, OR, and XOR operations are performed.
For example, a sample bitwise AND operation is shown here:
0 1 0 0   1 1 0 1
      &
0 0 1 1   1 0 1 1
0 0 0 0   1 0 0 1
A bitwise OR operation looks like this:
0 1 0 0   1 1 0 1
     |
0 0 1 1   1 0 1 1
0 1 1 1   1 1 1 1
A bitwise XOR operation is shown here:
0 1 0 0   1 1 0 1
      ^
0 0 1 1   1 0 1 1
0 1 1 1   0 1 1 0

The One’s Complement Operator

The one’s complement operator, ~, will invert all the bits in its operand. For example, if a character variable, ch, has the bit pattern
0 0 1 1   1 0 0 1
then
ch = ~ch;
places the bit pattern
1 1 0 0   0 1 1 0
into ch.

The Shift Operators

The right (>>) and left (<<) shift operators shift all bits in an integral value by the specified amount. As bits are shifted off one end, zeros are brought in the other end. (If the value being shifted is a negative, signed number and a right shift is performed, then ones are shifted in to preserve the sign.) The number on the right side of the shift operator specifies the number of positions to shift. The general form of each shift operator is
value >> number 
value << number
Here, number specifies the number of positions to shift value.
Given this bit pattern (and assuming an unsigned value),
0 0 1 1   1 1 0 1
a shift right yields
0 0 0 1   1 1 1 0
while a shift left produces
0 1 1 1   1 0 1 0


Programming Tip 
A shift right is effectively a division by 2, and a shift left is a multiplication by 2. For many computers, a shift is faster than a multiply or a divide. Therefore, if you need a fast way to multiply or divide by 2, consider using the shift operators. For example, the following code fragment will first multiply and then divide the value in x by 2:
int x;

x = 10;
x = x << 1;
x = x >> 1;
Of course, when using the shift operators to perform multiplication, you must be careful not to shift bits off the end.

Pointer Operators

The two pointer operators are * and &. A pointer is an object that contains the address of another object. Or, put differently, an object that contains the address of another object is said to “point to” the other object.

The & Pointer Operator

The & operator returns the address of the object it precedes. For example, if the integer x is located at memory address 1000, then
p = &x;
places the value 1000 into p. The & can be thought of as “the address of.” For example, the previous statement could be read as “place the address of x into p.”

The * Pointer Operator

The * is the indirection operator. It uses the current value of the variable it precedes as the address at which data will be stored or obtained. For example, the following fragment
p = &x; /* put address of x into p */
*p = 100; /* use address contained in p */
 
places the value 100 into x. The * can be remembered as “at address.” In this example, it could be read, “place the value 100 at address p.” Since p contains the address of x, the value 100 is actually stored in x. In words, p is said to “point to” x. The * operator can also be used on the right-hand side of an assignment. For example,
p = &x;
*p = 100;
z = *p / 10;
 
places the value of 10 into z.

Assignment Operators

In C/C++, the assignment operator is the single equal sign. When assigning a common value to several values, you can “string together” several assignments. For example,
a = b = c = 10;
 
assigns a, b, and c the value 10.
There is a convenient “shorthand” for assignments that have this general form:
var = var op expression;
Assignments of this type can be shortened to
var op = expression;
For example, these two assignments
x = x+10;
y = y/z;
 
can be recoded as shown here:
x += 10;
y /= z;

The ? Operator

The ? operator is a ternary operator (it works on three expressions). It has this general form:
expression1 ? expression2 : expression3;
If expression1 is true, then the outcome of the operation is expression2; otherwise, it is the value of expression3.


Programming Tip 
The ? is often used to replace if-else statements of this general type:
if(expression1)  var = expression2;
else var = expression3; 
 
For example, the sequence
if(y < 10) x = 20;
else x = 40;

can be rewritten like this:
x = (y<10) ? 20 : 40;
 
Here, x is assigned the value of 20 if y is less than 10 and 40 if it is not.
One reason that the ? operator exists, beyond saving typing on your part, is that the compiler can produce very fast code for this statement—much faster than for the similar if-else statements.

Member Operators

The . (dot) operator and the > (arrow) operator are used to reference individual members of classes, structures, and unions. The dot operator is applied to the actual object. The arrow operator is used with a pointer to an object. For example, given the following structure:
struct date_time {
  char date[16];
  int time;
} tm;
 
to assign the value "3/12/2003" to the date member of object tm, you would write
strcpy(tm.date, "3/12/2003");
 
However, if p_tm is a pointer to an object of type date_time, the following statement is used:
strcpy(p_tm->date, "3/12/2003");

The Comma Operator

The comma operator causes a sequence of operations to be performed. The value of the entire comma expression is the value of the last expression of the comma-separated list. For example, after execution of the following fragment,
y = 15;
x = (y=y-5, 50/y);
 
x will have the value 5 because y’s original value of 15 is reduced by 5 and then that value is divided into 50, yielding 5 as the result. You can think of the comma operator as meaning “do this and this” and so on.
The comma operator is used most often in the for statement. For example,
for(z=10, b=20; z<b; z++, b--) { // ...
 
Here, z and b are initialized and modified using comma-separated expressions.

sizeof

Although sizeof is also a keyword, it is a compile-time operator that determines the size, in bytes, of a variable or data type, including classes, structures, and unions. If used with a type, the type name must be enclosed by parentheses.
For most 32-bit compilers, the following example prints the number 4:
int x;
cout << sizeof x;
 
For C99, sizeof is evaluated at runtime when it is applied to a variable-length array.

The Cast

A cast is a special operator that forces one data type to be converted into another. Both C and C++ support the form of cast shown here:
(type) expression
where type is the desired data type.
For example, the following cast causes the outcome of the specified integer division to be of type double:
double d;
d = (double) 10/3;

C++ Casts

C++ supports additional casting operators. They are const_cast, dynamic_ cast, reinterpret_cast, and static_cast. Their general forms are shown here:
const_cast<type> (expr)
dynamic_cast<type> (expr)
reinterpret_cast<type> (expr)
static_cast<type> (expr)
Here, type specifies the target type of the cast and expr is the expression being cast into the new type.
The const_cast operator is used to explicitly override const and/or volatile in a cast. The target type must be the same as the source type except for the alteration of its const or volatile attributes. The most common use of const_cast is to remove constness.
dynamic_cast performs a runtime cast that verifies the validity of the cast. If the cast cannot be made, the cast fails and the expression evaluates to null. Its main use is for performing casts on polymorphic types. For example, given two polymorphic classes B and D, with D derived from B, a dynamic_ cast can always cast a D* pointer into a B* pointer. A dynamic_cast can cast a B* pointer into a D* pointer only if the object being pointed to actually is a D object. In general, dynamic_cast will succeed if the attempted polymorphic cast is permitted (that is, if the target type can legally apply to the type of object being cast). If the cast cannot be made, then dynamic_ cast evaluates to null if the cast involves pointers. If it fails on a reference, a bad_cast exception is thrown.
The static_cast operator performs a nonpolymorphic cast. For example, it can be used to cast a base class pointer into a derived class pointer. It can also be used for any standard conversion. No runtime checks are performed The reinterpret_cast operator changes one type into a fundamentally different type. For example, it can be used to change a pointer into an integer. A reinterpret_cast should be used for casting inherently incompatible pointer types.
Only const_cast can cast away constness. That is, neither 
dynamic_cast, static_cast, nor reinterpret_cast can alter the constness of an object.

The I/O Operators

In C++, the << and the >> are overloaded to perform I/O operations. When used in an expression in which the left operand is a stream, the >> is an input operator and the << is an output operator. In the language of C++, the >> is called an extractor because it extracts data from the input stream. The << is called an inserter because it inserts data into the output stream. The general forms of these operators are shown here:
input-stream >> variable;
output-stream << expression
For example, the following fragment inputs two integer variables:
int i, j;
cin >> i >> j;
 
The following statement displays “This is a test 10 20”:
cout << "This is a test " << 10 << << ' ' << 4*5;
 
The I/O operators are not supported by C.

The .* and –>* Pointer-to-Member Operators 

C++ allows you to generate a special type of pointer that “points” generically to a member of a class, not to a specific instance of that member in an object. This sort of pointer is called a pointer to a member, or pointer-to- member, for short. A pointer to a member is not the same as a normal C++ pointer. Instead, a pointer to a member provides only an offset into an object of the member’s class at which that member can be found. Since member pointers are not true pointers, the . and > operators cannot be applied to them. To access a member of a class given a pointer to it, you must use the special pointer-to-member operators .* and >*. They allow you to access a member of a class given a pointer to that member.
When you are accessing a member of an object given an object or a reference to an object, use the .* operator. When accessing a member given a pointer to an object, use the >* operator.
A pointer to a member is declared by using the general form shown here:
type class-name::*ptr;
Here, type is the base type of the member, class-name is the name of the class, and ptr is the name of the pointer-to-member variable being created. Once created, ptr can point to any member of its class that is of type type.
Here is a short example that demonstrates the .* operator. Pay special attention to the way the member pointers are declared.
#include <iostream>
using namespace std;

class cl {
public:
  cl(int i) { val=i; }
  int val;
  int double_val() { return val+val; }
};

int main()
{
  int cl::*data; // int data member pointer
  int (cl::*func)(); // func member pointer
  cl ob1(1), ob2(2); // create objects
  
  data = &cl::val; // get offset of val
  func = &cl::double_val;  // get offset

  cout << "Here are values: ";
  cout << ob1.*data << " " << ob2.*data << "\n";

  cout << "Here they are doubled: ";
  cout << (ob1.*func)() << " ";
  cout << (ob2.*func)() << "\n";

  return 0;
}
 
The pointer-to-member operators are not supported by C.

The :: Scope Resolution Operator

The :: scope resolution operator specifies the scope to which a member belongs. It has this general form:
name::member-name
Here, name is the name of the class or namespace that contains the member specified by member-name. Put differently, name specifies the scope within which can be found the identifier specified by member-name.
To reference the global scope, you do not specify a scope name. For example, to refer to a global variable called count that is being hidden by a local variable called count, you can use this statement:
::count
The scope resolution operator is not supported by C.

new and delete


new and delete are C++’s dynamic allocation operators. They are also keywords. See Chapter 5 for details.
C does not support the new and delete operators.

typeid

In C++, the typeid operator returns a reference to a type_info object, which describes the type of the object to which typeid is being applied. typeid has this general form:
typeid(object)
typeid supports runtime type identification (RTTI) in C++. Your program must include the header <typeinfo> in order to use typeid.
The type_info class defines the following public members:
bool operator==(const type_info &ob) const;
bool operator!=(const type_info &ob) const;
bool before(const type_info &ob) const;
const char *name( ) const;
The overloaded == and != provide for the comparison of types. The before( ) function returns true if the invoking object is before the object used as a parameter in collation order. (This function is mostly for internal use only. Its return value has nothing to do with inheritance or class hierarchies.) The name( ) function returns a pointer to the name of the type.
When typeid is applied to a base class pointer of a polymorphic class, it will automatically return the type of the object being pointed to. (A polymorphic class is one that contains at least one virtual function.) Thus, typeid can be used to determine the type of object pointed to by a base class pointer. The same is true for a base class reference.
typeid is not supported by C.

Operator Overloading

In C++, operators can be overloaded by using the operator keyword. (See Chapter 5.) Operator overloading is not supported by C.

Operator Precedence Summary

The following table lists the precedence of all C and C++ operators. Please note that all operators, except the unary operators, the assignment operators, and ?, associate from left to right.
Precedence
Operators
Highest
( )   [ ]   –>   ::   .
!   ~   ++   – –  –   *   &   sizeof   new   delete
                                     typeid   type-casts
.*   –>*
*   /   %
+   –
<<    >>
<    <=    >    >=
==    !=
&
^
|
&&
||
?:
=    + =    – =    *=    /=    %=    >> =    << =    & =    ^ =    |=  
Lowest
'

The precedence of the bitwise operators is shown here:
Precedence
Operators
Highest
~
>>   <<
&
^


Followers