You're in
Iker Hurtado's pro blog
Developer | Entrepreneur | Investor
Software engineer (entrepreneur and investor at times). These days doing performant frontend and graphics on the web platform at Barcelona Supercomputing Center

Relearning C++: Notes on statements, expressions and operators

5 Mar 2015   |   iker hurtado  
Share on Twitter Share on Google+ Share on Facebook
In this post I write down some notes as from my study of C++ basics on statements, expressions and operators

The assignment statement

The assignment statement works this way: the expression on the right-hand-side (RHS) is evaluated to produce a resultant value (rvalue). The rvalue is then assigned to the variable on the left-hand-side (LHS) (lvalue, location that can hold a rvalue). The type of the result is the type of the left-hand operand. If the types of the left and right operands differ, the right-hand operand is converted to the type of the left.

More on lvalues and rvalues

Every expression in C++ is either an rvalue or an lvalue.

An object can act as an rvalue, then we use the object’s value (its contents) or it can act as an lvalue, then we use the object’s identity (its location in memory).

It's important to note that with operators it's possible to use an lvalue in an rvalue place, but we cannot use an rvalue in an lvalue (i.e., a location) place. When we use an lvalue in place of an rvalue, the object’s contents are used.

Some notes on operators

the arithmetic operators may be applied to any of the arithmetic types or to any type that can be converted to an arithmetic type. The operands and results of these operators are rvalues. The relational operators take operands of arithmetic or pointer type; the logical operators take operands of any type that can be converted to bool. The operands to these operators are rvalues and the result is an rvalues.

Each compound operator (+= -= *= /= %=) is equivalent to a = a op b, excepting that the left-hand operand is evaluated only once (not twice).

The increment (++) and decrement (--) operators provide a convenient notational shorthand for adding or subtracting 1 from an object. Its use is mandatory with iterators that do not support arithmetic operations.

There are two forms of these operators: prefix and postfix. The prefix operators return the object itself as an lvalue. The postfix operators return a copy of the object’s original value as an rvalue.

Use Postfix Operators only When Necessary
The prefix version saves work: it increments the value and returns the incremented version. The postfix operator must store the original value. So if we don’t need the unincremented value, there’s no need for that extra work -for ints and pointers, the compiler can optimize away this extra work.
Understanding the typical iterator increment in loops (*pbeg++)
The precedence of postfix increment is higher than that of the dereference operator, so *pbeg++ is equivalent to *(pbeg++). The subexpression pbeg++ increments pbeg and yields a copy of the previous value of pbeg as its result. Accordingly, the operand of * is the unincremented value of pbeg. Thus, the statement prints the element to which pbeg originally pointed and increments pbeg.

Notes on loops

In some cases, in a for loop it may be useful to execute more than one instruction as any of initialization, condition, or statement. As expressions, they can make use of the comma operator (,) that can separate multiple expressions where only one is generally expected.

Range for statement

In C++11 standard was introduced a simpler for statement that can be used to iterate through the elements of a container or other sequence. The syntactic form is:

for (declaration : expression)

for (char c : str)
for (auto c : str)

expression must represent a sequence, such as a braced initializer list, an array or an object of a type such as vector or string that has begin and end members that return iterators.

declaration defines a variable. It must be possible to convert each element of the sequence to the variable’s type. In order to ensure that the types match we can use the auto type specifier. If we want to modify the elements in the sequence, the variable must be a reference type.

Otherwise, we cannot use a range for to add elements to a container: the end() value is cached, then if we add elements to (or remove) the sequence, the end value might be invalidated.

Variables defined in a while condition or while body (and for body?) are created and destroyed on each iteration.