- C++ provides a set of operators and defines how they operate on native types
- Operator overloading is allowed when operators operate between classes
expression
Consists of one or more operators/operands that evaluate an expression and return the result. Complex expressions can be obtained by combining operators with operands.
basis
- When an object is used as an rvalue, the object’s value (content) is used; when an object is used as an lvalue, the object’s identity (location in memory) is used.
- Except for an rvalue reference, everything that requires an rvalue can be replaced by an lvalue, and vice versa. When an lvalue is used as an rvalue, its value is used.
- The left and right values of the operator require:
- The assignment operator
=
A nonscalar lvalue is required as the left-hand object, and the return result is also an lvalue - Address-of operator
&
Returns a pointer to an lvalue object that is an rvalue - Built-in dereference
*
, built-in subscript[]
, iterator dereference*
, string, and vector[]
, they all return lvalues - Increments of built-in and iterator
++
diminishing--
Applied to an lvalue object, the pre-version of which returns an lvalue - If the expression evaluates to an lvalue, then
decltype
As a result of theReference types
. For example,int *p
; odecltype(*p)
As a result of theint &
- The assignment operator
Prior knowledge: lvalue and rvalue
- Definition:
lvalue
(Locator value) represents an object that occupies a specific location in memory (in other words, has an address).rvalue
Defined by exclusivity, each expression is either LValue or Rvalue. So from the above definition of lvalue, an rvalue is an expression that does not occupy a certain location in memory.
Example:
int var; var = 4; // corret 4 = var; // error! '4' is a temporary intermediate variable in the code, which is only a temporary storage in the register, and has no definite locate (var + 1) = 4; // error ! Int a = 1; int a = 1; int& foo() {return a; } int main() { foo() = 10; // the reference to a is changed to 10, the address store value is changed to return 0; }Copy the code
Arithmetic operator
- Small integers are promoted before an arithmetic expression is evaluated. All objects are eventually converted to the same type
- Unary plus, plus and minus can be used for Pointers. A unary plus on a pointer or arithmetic value returns a copy, and a unary minus on an object’s value returns a copy.
- division
/
Earlier versions of C++ allowed rounding up or down if the result was negative. After C++11, the quotient rule was specifiedTo zero integer
, that is, cut out the decimal part directly. - Take over operations
%
, if m and n are integers and n is non-0, then the expression(m/n)*n+m%n
The result of is m. That is, ifm%n
It is not 0,The sign is the same as m
. Earlier versions of C++ allowedm%n
Symbol matching ofn
And the quotient is rounded on the negative infinity side, butBanned in C++11
. Except for the special case where -m causes an overflow,(-m)/n
andm/(-n)
Will be equal to-(m/n)
.m%(-n)
Is equal to them%n
.(-m)%n
Is equal to the-(m%n)
Logical and relational operators
- Logic and
&&
, logic, or||
Are short circuit evaluation, the left side first, only from the left side can not determine the result of the expression and then the right side.- Logic and
&&
We only find the right-hand side if the left-hand side is true - Logic or
||
We only find the right-hand side if the left-hand side is false
- Logic and
- Unlike Python, in C++
int a == true
Only when thea = 1
When is true
The assignment operator
- If the left and right types do not match, convert the right to the left type.
- C++ allows the result of an assignment to be a condition, so
=
and= =
Want to distinguish. The return value of assignment is the left-hand object. - Compound operators are faster: compound operators
a+=b
Evaluate only once, common operatora=a+b
Evaluate twice, add once and assign once.
Increment and decrement operators
- Both increment and decrement characters operate on lvalue objects.
++i
It’s called the pre-release,i++
This is called a post-release.- The differences between pre-release and post-release:
- The pre-version will object
+ 1
or- 1
The object itself is returned as an lvalue - The post-version will object
+ 1
or- 1
A copy of the object’s original value is returned as an rvalue
- The pre-version will object
- Use the pre-release version whenever possible, because there is one less copy than the post-release version, avoiding unnecessary work.
- A mixture of dereferencing and incrementing achieves brevity:
cout<<*iter++;
Is equivalent tocout<<*iter; ++iter;
Member access operator
- Some operators
.
Gets a member of the class object, the arrow operator->
By the reference solution*
And dot operators.
, i.e.ptr->mem
Is equivalent to(*ptr).mem
The parentheses cannot be omitted becausePoint priority is higher than dereference
. - The arrow operator acts on a pointer to get the member of the object, resulting in an lvalue. (Because dereferencing is always a reference, and a reference is an lvalue)
- The dot operator depends on the object: it returns an lvalue if the object is an lvalue, and an rvalue if the object is an rvalue.
Conditional operator
- The conditional operator satisfies the right associative law, i.e
a? b:c? d:e
Should be interpreted asa? b:(c? d:e)
An operator
- When the bitwise operator encounters a small integer (bool, char, short, etc.), it is automatically promoted before being evaluated.
- If the bitwise operator’s operand is signed and has a negative value, the way the symbol bits are handled depends on the machine. Shifting left and right changes sign bits and is undefined.
- Shift operator
<<
and>>
: Causes the left operand to move the specified number of bits as requested by the right operand, then the moved (possibly promoted) copy of the left operand is the result. The right object must not be negative, and the value must be strictly less than the left digit. Bits removed from the boundary are discarded. - The shift operator satisfies the left associative law
- The left shift operator inserts right
0
The right shift operator inserts a value to the left depending on the type and machine:unsigned
Type insert0
.signed
The type depends on the machine and the encoding.
The sizeof operator
sizeof
The operator returns the number of bytes in an expression or a type that satisfies the right associative lawize_t
Type ofconstant
Expression.- Two forms:
sizeof(type)
,sizeof expr
sizeof
Operations do not evaluate the operand’s value, so we can:- in
sizeof
Invalid Pointers are dereferenced, because dereferencing does not actually happen. - in
sizeof
Use the domain operator directly in: :
To get the size of a class member without requiring an object or member.
- in
- The sizeof operator applies to different objects differently:
- The char expression returns 1
reference
Do the sizeof returnsReferenced object
The amount of space occupiedPointer to the
Do the sizeof returnsThe pointer itself
The amount of space occupiedDereference pointer
Do the sizeof returnsPointing to the object
The amount of space occupiedAn array of
Do the sizeof getThe entire array
Attention: sizeof does not treat arrays as Pointers.string
orvector
Sizeof returns onlyFixed part
The size of the object does not calculate the actual space occupied by the object
Common uses: sizeof(ia)/sizeof(*ia) Is used to calculate the length of an array.
int arr[10]; constexpr int len = sizeof(arr) / sizeof(*arr); Cout << len << endl; constexpr int INPUT_H = 608; constexpr int INPUT_W = 1088;Copy the code
Type conversion
Type conversion is divided into implicit conversion and explicit conversion. Implicit conversion occurs in the following situations:
- The integer promotion
- Conditional non-bool to bool
- When initialized, the initial value is changed to the variable type, and when assigned, the right object is changed to the left type
- There are multiple types of arithmetic or relational operations that will eventually be unified
- Function calls also have type conversions
Arithmetic conversion
Arithmetic conversion
: Converts an operand (arithmetic type) to the widest type. Converts an integer to a floating point if both are present.The integer promotion
: Converts a small integer to a large integer.- Small integers (bool, char, signed char, unsigned char, short, unsigned short, etc.) are converted to int if the value can fit into an int, and to unsigned int if it cannot fit into an int
- Wide characters (wchar_t, CHAR16_t, char32_t) are promoted to the smallest that can fit in an int, unsigned int, long, unsigned long, long long, and unsigned long
Conversion of signed to unsigned
:- If the unsigned type is not less than the signed type, convert signed to unsigned
- If the unsigned type is smaller than the signed type, and all the values of the unsigned type can fit into the signed type, then unsigned becomes signed
- If the unsigned type is smaller than the signed type, and not all of the values of the unsigned type fit into the signed type, then signed becomes unsigned
Case example:
bool flag; char cval; short sval; unsigned short usval; int ival; unsigned int uival; long lval; unsigned long ulval; float fval; double dval; 3.14159 L + 'a'; // long double dval+ival; / / ival double dval + fval; / / fval double ival = dval; Int flag=dval; // if dval is 0 then false, otherwise true // float sval+cval; // both sval and cval are promoted to int cval+lval; / / cval long ival + ulval; Unsigned long usval+ival; Uival +lval; uival+lval; uival+lval; // Undefined, convert according to the size of space occupied by unsigned int and longCopy the code
Other implicit type conversions
- Array rotation pointer:
- In most expressions that use arrays, the array is automatically converted to a pointer to the first element
- Using a function type in an expression also converts to a function pointer
- Exception:
decltype
And take the address&
,sizeof
,typeid
Operator does not convert an array to a pointer - Exception:
reference
The pointer is not rotated when the array is initialized
- Pointer conversion:
0
ornullptr
Can be converted to any pointer type- Point to any
Very content
Pointer can be converted tovoid *
- Point to any
object
Pointer can be converted toconst void *
- Conversion to constant: Allows a pointer or reference to a nonconstant to be converted to a pointer or reference to a constant. But otherwise, the underlying const cannot be deleted.
- Conversion of class types: Class types can define conversions, but the compiler can perform only one conversion.
Off topic: review the bottom, top const
- Pointer to constant (underlying COsnt) :You cannot change its pointer to the content. Const int can be declared before and after the type name. In the case of int, const int and int const are equivalent. Declaring a pointer to a constant is justThe underlying const.
- Pay attention toA pointer to a “constant” does not mean that what it points to is a constant, but that it cannot be dereferenced by the operator
*
) to change what it points to. It is still possible to implement a pointer to a value by modifying the pointing object directly.
- Pay attention toA pointer to a “constant” does not mean that what it points to is a constant, but that it cannot be dereferenced by the operator
int num_a = 1; int const *p_a = &num_a; // bottom const //*p_a = 2; Cout << *p_a << endl; cout << *p_a << endl; num_a = 2; Cout << "after: "<< *p_a << endl; // It has been changed to 2Copy the code
- Pointer constant: Indicates that the pointer itself is a constant and must be declared
Initialize the
And then it storesAddress values
You can’t change it. When the statementconst
Must be placed in pointer symbol*
Hereafter, namely:*const
. The declared constant pointer is the top layerconst
int num_b = 2; int *const p_b = &num_b; // top-level const //p_b = &num_a; // Error, constant pointer cannot change stored address valueCopy the code
- Distinguishing function: illustrate with examples
const int a = 1; //int * pi = &a; Const int * PI = &a; Const ppi = &pi, const ppi = &pi, const ppi = &pi Const int *const *pppi = &ppi; / / underlying constCopy the code
Explicit conversion
Cast casting
It is often dangerous to manually specify what variables to convert and what types to convert.- The explicit conversion form is
cast-name<type>(expression)
, if type is a reference typeThe left value
. Cast – is the namestatic_cast
,dynamic_cast
,const_cast
,reinterpret_cast
One of them. static_cast
: can be used as long as it does not contain the underlying const. Examples include converting a large arithmetic type to a small arithmetic type, floating point to integer, and type conversions that the compiler cannot perform automatically- available
static_cast
Retrieval exists invoid *
A value in a pointer that is cast to its original type. - Example:
static_cast
backvoid *
Values in Pointers
Double d = 3.14; void *p=&d; Double *dp=stataic_cast<double *>(p); // Turn the pointer back to doubleCopy the code
const_cast
: Only the underlying const of an object can be changed. (attention:The underlying const cannot be written to after const_cast is removed. This is undefined.)- If the object is a constant, it is undefined to write after removing the constant with const_cast.
- Const_cast is used in contexts where functions are overloaded, but not otherwise.
reinterpret_cast
: Provides a low-level reinterpretation of the operand’s bit pattern, i.e. the bits in memory remain unchanged, changing the way they are read. It relies on machines and is very dangerous.- It is recommended to avoid casts, especially reinterpret_casts
- In early C++, explicit type conversions were of the form
type(expr)
and(type)expr
. An old-style cast is also valid for const_cast and static_cast somewhere, treated as const_cast and static_cast, and treated as reinterpret_cast otherwise. It is not recommended to use it because it is unknown.