• C++ provides a set of operators and defines how they operate on native types
  • Operator overloading is allowed when operators operate between classes
  • expressionConsists 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, thendecltypeAs a result of theReference types. For example,int *p; odecltype(*p)As a result of theint &

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).
    • rvalueDefined 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%nThe result of is m. That is, ifm%nIt is not 0,The sign is the same as m. Earlier versions of C++ allowedm%nSymbol matching ofnAnd the quotient is rounded on the negative infinity side, butBanned in C++11. Except for the special case where -m causes an overflow,(-m)/nandm/(-n)Will be equal to-(m/n).m%(-n)Is equal to them%n.(-m)%nIs 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
  • Unlike Python, in C++int a == trueOnly when thea = 1When 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 operatorsa+=bEvaluate only once, common operatora=a+bEvaluate twice, add once and assign once.

Increment and decrement operators

  • Both increment and decrement characters operate on lvalue objects.
  • ++iIt’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+ 1or- 1The object itself is returned as an lvalue
    • The post-version will object+ 1or- 1A copy of the object’s original value is returned as an rvalue
  • 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->memIs equivalent to(*ptr).memThe 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.ea? b:c? d:eShould 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 right0The right shift operator inserts a value to the left depending on the type and machine:unsignedType insert0.signedThe type depends on the machine and the encoding.

The sizeof operator

  • sizeofThe operator returns the number of bytes in an expression or a type that satisfies the right associative lawize_tType ofconstantExpression.
  • Two forms:sizeof(type),sizeof expr
  • sizeofOperations do not evaluate the operand’s value, so we can:
    • insizeofInvalid Pointers are dereferenced, because dereferencing does not actually happen.
    • insizeofUse the domain operator directly in: :To get the size of a class member without requiring an object or member.
  • The sizeof operator applies to different objects differently:
    • The char expression returns 1
    • referenceDo the sizeof returnsReferenced objectThe amount of space occupied
    • Pointer to theDo the sizeof returnsThe pointer itselfThe amount of space occupied
    • Dereference pointerDo the sizeof returnsPointing to the objectThe amount of space occupied
    • An array ofDo the sizeof getThe entire arrayAttention: sizeof does not treat arrays as Pointers.
    • stringorvectorSizeof returns onlyFixed partThe 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:decltypeAnd take the address&,sizeof,typeidOperator does not convert an array to a pointer
    • Exception:referenceThe pointer is not rotated when the array is initialized
  • Pointer conversion:
    • 0ornullptrCan be converted to any pointer type
    • Point to anyVery contentPointer can be converted tovoid *
    • Point to anyobjectPointer 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.
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 declaredInitialize theAnd then it storesAddress valuesYou can’t change it. When the statementconstMust 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 castingIt is often dangerous to manually specify what variables to convert and what types to convert.
  • The explicit conversion form iscast-name<type>(expression), if type is a reference typeThe left value. Cast – is the namestatic_cast,dynamic_cast,const_cast,reinterpret_castOne 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
  • availablestatic_castRetrieval exists invoid *A value in a pointer that is cast to its original type.
  • Example:static_castbackvoid *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 formtype(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.

Operational priority