Expressions
Expressions are something that can be evaluated to produce a value.
The simplest kind of expression is when you write a variable name or a single literal. You can also make a more sophisticated expressions using operators.
Operators
Arithmetic operators
Unary arithmetic operators+a(unary plus) — gets the value ofa(unnecesarry in most cases), and promote the type of the result toint-a(unary minus) — negates the value ofa(plus to minus, vice versa), and promote the type of the result toint
a + b(addition) — addsaandba - b(subtraction) — subtractsawithba * b(multiplication) — multipliesaandba / b(division) — dividesawithba % b(modulo) — computes the reminder ofadivided byb
a++— gets the current value ofa, then increments the value ofaby 1a--— gets the current value ofa, then decrements the value ofaby 1++a— increments the value ofaby 1, then gets the new value ofa--a— decrements the value ofaby 1, then gets the new value ofa
Assignment operators
Normal assignmenta = b— assignsbtoa, then gets the value ofa
a += b— equivalent toa = a + ba -= b— equivalent toa = a - ba *= b— equivalent toa = a * ba /= b— equivalent toa = a / ba %= b— equivalent toa = a % ba &= b— equivalent toa = a & ba |= b— equivalent toa = a | ba ^= b— equivalent toa = a ^ ba <<= b— equivalent toa = a << ba >>= b— equivalent toa = a >> b
Relational operators
Equality operatorsa == b(equality) — returnstrueifa=b, otherwise returnfalsea != b(inequality) — returnstrueifa≠b, otherwise returnfalse
a < b— returnstrueifa<b, otherwise returnfalsea > b— returnstrueifa>b, otherwise returnfalsea <= b— returnstrueifa≤b, otherwise returnfalsea >= b— returnstrueifa≥b, otherwise returnfalse
Logical operators
Logical operatorsa && b(logical AND) — returnstrueifaandbis bothtrue,falseotherwisea || b(logical OR) — returnstrueif eitheraorbistrue,falseotherwise!a(logical NOT) — returnstrueifaisfalse,falseotherwise
a & b(bitwise AND) — performs boolean AND operation on each bit ofaandb, e.g.0b0011 & 0b0101⇒0b0001a | b(bitwise OR) — performs boolean OR operation on each bit ofaandb, e.g.0b0011 | 0b0101⇒0b0111a ^ b(bitwise XOR) — performs boolean XOR operation on each bit ofaandb, e.g.0b0011 ^ 0b0101⇒0b0110~a(bitwise NOT) — inverts all bits ofa
a << b(shift left) — shifts inbzero bits to the right ofa(the left-mostbbits are discarded), e.g.0b0011 << 1⇒0b0110a >> b(shift right) — shifts inbzero bits to the left ofa(the right-mostbbits are discarded), e.g.0b0011 >> 1⇒0b0001
Miscellaneous operators
Subscript operatora[b]— gets the element at indexbfrom arraya
a.b— gets memberbfrom objectaa->b— gets memberbfrom pointera
&a— gets the address ofa*a— gets the value stored by pointera
a::b— gets memberbin class/namespacea::b— gets variablebin the global namespace
fn()— calls functionfn, optionally with parameters (e.g.fn(a, b, c)), returning the return value from the function call
throw a— throws an exception with the valuea(which could be an error code, a description of the problem, or a custom exception class, learncpp.com)
new type— allocates storage for an object of typetype, returning a pointer to the allocated objectnew type[]— allocates storage for an array of typetype, optionally with length (e.g.new type[length]), returning a pointer to the allocated arraydelete a— deallocates storage for objecta("deallocates a single variable")delete[] a— deallocates storage for arraya("deallocates multiple variables")
type(a)— castsato the new typetype(functional cast)type{a}— castsato the new typetype(functional cast, C++11)(type)a— castsato the new typetype(C-style cast)static_cast<type>(expr)— castsexprto typetypedynamic_cast<type>(expr)— castsexprto typetypewith runtime type-checking (becomesnullptrif the casting is invalid)const_cast<type>(expr)— removesconstproperty from pointer or referenceexprreinterpret_cast<type>(expr)— interprets the value stored at addressexpras typetype(usually for low-level programming)
a ? b : c(ternary operator) — ifais true, returnsb, otherwise returnsca <=> b(three-way comparison) — ifa < b, returns a negative value; ifa > b, returns a positive value; ifa == b, returns 0a, b(comma operator) — RARELY USED: evaluatesa, then evaluatesb, then returnsb(returns the right-most operand)sizeof(a)— gets the size of objectaOR typea, in bytes
Operator precendence and associativity
When multiple operator appears in one statement, operator precendence and operator associativity rules govern how to read the expression (which part should be performed first)
Operator precendence
Operators with higher precendence should be performed first.
- Use parentheses
(...)to enforce precendence - Remember PEMDAS in math (
*'s and/'s are performed before+'s and-'s) - Logical AND has higher precendence than OR (
&&'s are performed before||'s)
Operator associativity
If two operators have the same precendence (e.g. / and *), operator associativity rule tells us whether we should read it left-to-right or right-to-left.
For example, a * b * c should be read as (a * b) * c, because * have left-to-right associativity (read it from left to right).
Evaluation order
Operator precendence and associativity rules only tell which part of the expression should be evaluated first in relation to other operators.
Given a + (b * c) or f(a, b, c), the specification does not tell whether the compiler should evaluate a, b, or c first. The compiler is free to choose whatever order it likes (for optimization).
Enforcing evaluation order
To enforce certain evaluation order, separate the expression into separate statements:
// The compiler can choose any evaluation order
// e.g. `roll()` can be called first before `stop()`
result = (stop() * drop()) + roll();
// Enforcing evaluation order
int temp =
result = stop();
result += drop();
result += roll();
Lazy evaluation
Also called short-circuit evaluation:
- In
a && b— ifaisfalse, then the whole expression isfalse, so there is no need to evaluateb(it is not evaluated and its side effects are not executed) - In
a || b— ifaistrue, then the whole expression istrue, so there is no need to evaluateb(it is not evaluated and its side effects are not executed)
References
- C++ Crash Course (Josh Lospinoso) — 7. Expressions
- 5.1 — Operator precedence and associativity — https://www.learncpp.com/cpp-tutorial/operator-precedence-and-associativity/
- 5.5 — Comma and conditional operators — https://www.learncpp.com/cpp-tutorial/comma-and-conditional-operators/
- 5.6 — Relational operators and floating point comparisons — https://www.learncpp.com/cpp-tutorial/relational-operators-and-floating-point-comparisons/
- 5.7 — Logical operators — https://www.learncpp.com/cpp-tutorial/logical-operators/
- 20.2 — Basic exception handling — https://www.learncpp.com/cpp-tutorial/basic-exception-handling/
- Comparison operators — https://en.cppreference.com/w/cpp/language/operator_comparison