Skip to content

Chapter 1: The Basics

1.1

C++'s model of memory and computation, and the basic mechanisms for organizing code into a program.

1.2

For a program to run, its source text has to be processed by a compiler, producing object files, which are combined by a linker yielding an executable program. A C++ program tyically consists of many source code files (source files).

The ISO C++ standard defines two kinds of entities

  • Core Language Features, such as built-in types, and loops
  • Standard-library components, such as containers

1.2.1

If no value is returned (from main), the system will receive a value indicating successfuly completion. A nonzero value from main() indicates failure. Not every OS and execution environment make sure of that return value: Linux/Unix-based environments do, but Windows-based environments rarely do.

1.3

A function declaration may contains argument names. This can be a help to the reader of a program, but unless the declaration is also a function definition, the compiler simply ignores such name.

double sqrt(double d);
double square_root(double);

// member function of a class
char& String::operator[](int index); //type: char& String::(int)

1.4

Every name and every expression has a type that determins the operations that may be performed on it.

A declaration is a statement that introduces an entity into the program. It specifies a type for the entity:

  • A type defines a set of possible values and a set of operations (for an object)
  • An object is some memory that holds a value of some type. <-- note the difference between object and type
  • A value is a set of bits interpreted according to a type.
  • A variable is a named object.

A char variable is of the natural size to hold a character on a given machin, and the sizes of other types are multiples of the size of a char. the size of a type is implementation-defined, and can be obtained by the sizeof() operators. sizeof(char)==1.

Numbers:

  • floating numbers
  • integer literals: 0b11(binary), 0334 (octal), 0xBAD (hexadecimal)
  • ' as a digit separator: 1'000'0000, 3.141'5926

1.4.1

The order of evaluation of expressions is left to right, except for assignments, which are right-to-left. The order of evaluation of function arguments is unfortunately unspecified.

1.4.2

narrowing conversions, such as double to int and int to char, are allowed and implicitly applied when you use = (but not when you use {}). The problem caused by implicit narrowing conversions are a price paid for C compatibility.

1.5

A declaration introduces its name into a scope

  • local scope: A name declared in a function or a lambda is called a local name. A block is delimited by a {} pair. Function argument names are considered local names
  • Class scope: A name is called a member name (class member name) if it is defined in a class, outside any function/lambda/enum class. from the opening { of its enclosing declaration to the end of that declaration.
  • Namespace scope: A name is called a namespace member name if it is defined in a namespace outside any function, lambda, class, or enum class. from the declaration to the end of its namespace.
  • global name: A name not declared inside any other construct is called a global name and is said to be in the global namespace.
  • no name objects: temporaries or objects created using new.

1.6

immutability:

  • const: this is used primarily to specify interfaces so that data can be passed to functions using pointers and references without fear of it being modified. Value can be calculated at run time.
  • constexpr: this is used primarily to specify constants, to allow placement of data in read-only memory, and for performance. value must be calculated by the compiler

For a function to be usable in a constant expression, that is, in anexpression that will be evaluated by the compiler, it must be defined constexpr.

We allow a constexpr function to be called with non-constant-expression arguments in contexts that do not require constant expression. That way, we don't have to define essentially the same function twice: once for constant expressions, and once for variables. When we want a function to be used only for evaluation at compile time, we declare it consteval rather than constexpr

constexpr double square(double x) { return x * x;}
constexpr double max1 = 1.4 * square(17);   // OK
const double max2 = 1.4 * square(var);      // OK, evaled at run time

consteval double square2(double x) { return x * x;}
constexpr double max3 = 1.4 * square2(17);  // OK
const double max4 = 1.4 * square(var);      // ERROR: var is not a constant, square2 is consteval, cannot used at run time.

To be constexpr, a function must be rather simple and cannot have side effects and can only use information passed to it as arguments. In particular, it cannot modify non-local variables, but it can have loops and use its own local variables.

1.7

When used in declarations, operators (such as &, *, []) are called declarator operators.

1.7.1

we give the pointer the value nullptr. There is only one nullptr shared by all pointer types.

In older code, 0 or NULL is typically used instead of nullptr. However, using nullptr eliminates potential confusion between integer (such as 0/NULL) and pointers (such as nullptr)

1.8

switch/while/for. Also in for and if statement, a variable can be introduced

if (auto n = v.size(); n!= 0){}

1.9

The basic machine model for C and C++ is based on computer hardware, rather than some form of mathematics.

1.9.1

A reference and a pointer both refer/point to an object and both are represented in memory as a machine address. Assignment to a reference does not change what the reference refers to but assigns to the referenced object. (see difference between pointer and assignment)

1.9.2

Initialization differs from assignment. In general, for an assignment to work correctly, the assigned-to object must have a value. On the other hand, the task of initialization is to make an uninitialized piece of memory into a valid object.

You can use = to initialze a reference but please don't let that confuse you.

int& r = x; // bind r to x
This is still initialization and binds r to x, rather than any form of value copy.