C++ Cheatsheet
C vs. C++ Functionality
C Interoperability
C++ is a superset of C, but some C functionality has been superceded and should not typically be used in C++ code. One exception to this rule is when interacting with C code, sometimes we are forced to use C functionality.
malloc
and free
In C++, malloc
and free
should never be used. The new
and delete
operators should be used instead. These are type-safe, and they also ensure that the appropriate constructor and destructor is called.
Program Structure
Header Files
Header files (e.g. .h
, .hpp
) typically contain function declarations, while source files (e.g. .cpp
, .cc
) typically contain function definitions.
Source files can include
header files in order to gain access to the declarations therein. After compilation, it is the responsibility of linker to supply the appropriate definition for each referenced declaration; a header can tell the compiler that a function exists, but the compiler does not know where it is defined.
In theory everything could be defined in header files but this would drastically increase the compile time.
Include Guards
Each symbol (function, variable, etc.) can only be defined once. Otherwise how can the linker know which version is the correct one?
This is problematic when definitions are present in header files, as the same header files may be included multiple times within a program.
The solution for this is to use include guards:
#ifndef MY_HEADER_FILE_H
#define MY_HEADER_FILE_H
// header file contents
#endif
Memory Management
Memory Management
The practice of relying on constructor and destructors for memory management is sometimes referred to as Resource Acquisition Is Initialization (RAII).
Memory leaks are still possible if we forget to call delete
. One solution to this is to use smart pointers, which call new
and delete
automatically based on reference counting.
Heap vs. Stack
Using the new
operator creates an object on the heap, but by default objects are created on the stack. Stack-allocated objects are automatically deleted (and their destructor called) when they go out of scope, making them much easier and safer to use.
Stack-allocated objects are also cheaper to create and access, since their memory address can be determined at compile time. However, the stack size is very limited compared to the heap, so it should not be used for large objects.
Basic Syntax & Keywords
Right-Left Rule
The right-left rule allows us to reliably interpret complex type declarations. It is defined as follows:
- Start reading the declaration from the identifier.
- Read to the right until a closing bracket is reached.
- Read to the left until the matching bracket is found.
- Repeat from step 2, starting outside the brackets, until the whole declaration has been parsed.
Example:
int * (* (*fp1) (int) ) [10];
Start from the variable name: -> fp1
Read right, hit a bracket; go left to find * -> is a pointer
Read right again outside the brackets; find (int) -> to a function that takes an int
Hit another bracket; go left to find * -> and returns a pointer
Read right again outside the brackets; find [10] -> to an array of 10
Read left to find * -> pointers to
Keep reading left to find int -> ints
const
Variables, parameters and methods should be denoted as const
wherever possible to prevent accidental modification. const
methods of a class can only call other const
methods.
This is generally appropriate for getter methods (unless they return a reference to a member variable, because that would enable modification of that object).
East / west const
There is ongoing debate about whether the const
keyword should be placed to the left or to the right of a variable declaration. The former is arguably more natural, but the latter is more consistent.
constexpr
constexpr
should be used for variables and functions whose values can be determined at compile time. These can then be used in the declarations of const
variables.
noexcept
Functions that should never throw an exception can be marked noexcept
. This is a useful form of documentation, and it can allow certain optimisations by the compiler. Should such a function throw an exception, the program will terminate.
inline
These days, inline
is rarely needed, as the compiler generally knows when this kind of optimisation is appropriate. However, small functions defined in header files are good candidates for inline
.
inline
tells the compiler not to produce an error if a function definition is encountered multiple times, on the assumption that the function is defined in every translation unit where it is used, and that each definition is exactly the same.
Pointers & References
Pointer Declarations
Misleading Syntax
It is better to place the *
(or &
) next to the variable name, to prevent misleading declarations like this:
int* p, q;
In this example, only p
is actually a pointer.
This ambiguity can be resolved with the help of a typedef
. In this example, both p
and q
are pointers:
typedef int * IntPointer;
IntPointer p, q;
Pointers to Arrays
int tiles[32][4];
int (*p)[4] = tiles; // p is a pointer to an array of 4 ints;
// (`tiles` is equivalent to `tiles[0]`)
int *q[5]; // q is a pointer to an array of 5 ints
Function Pointers
Function pointers are declared using:
return_type (*variable_name)(function_params);
For example, here p
is a pointer to a function that takes 2 float
s and returns a pointer to a char
:
char * (*p)(float, float);
Arrow (->
) vs. Dot (.
)
The arrow is used when accessing an object's members, when we have a pointer to the object.
This dereferences the pointer before accessing the member. Dereferencing a pointer means getting the value that is stored in the memory location that the pointer points to.
In other words, foo->bar()
is the same as (*foo).bar()
.
Smart Pointers
TODO
TODO.
Collections
vector
TODO.
map
TODO.
Iterators
TODO.
Templates
TODO
TODO.
Classes
Constructors
TODO.
Destructors
TODO.
Copy Constructors
TODO.
Assignment Operators
TODO.
Rule of Five
TODO.
Inheritance
Virtual Destructors
TODO.
Pure Virtual
TODO.
Object Slicing
TODO.
Lambda Functions
TODO
TODO.
Credits
The following resources were used in the creation of this article:
Published 09/03/2021