File structure
Source files use the extension .cpp, header files use .h (or rarely .hpp).
Declarations belong in header files, definitions belong in source files. Identifiers can be declared more than once (which allows header files to be included multiple times without error), but can be defined at most once.
Source files are compiled individually, with no knowledge of the contents of other files. Header files allow identifiers to be used from other files, by allowing the required declarations to be included at the top of every file. Header files also prevent the issue of forward declarations in the same file.
Source files are individually compiled into object files, and then those object files are linked together into an executable.
Types
Fundamental integral types
All types are signed by default, unless prefixed with unsigned.
| Type | Width |
|---|---|
char |
at least 8 |
short |
at least 16 |
int |
at least 16 |
long |
at least 32 |
long long |
at least 64 |
int is the optimal integer size on the target platform.
bool is an integer type that can only hold the values 0 and 1.
wchar_t is a distinct type that is large enough to represent any supported character code point. This is 16 bits on Windows (uses UTF-16) and 32 bits on Linux (uses UTF-32). The types char8_t, char16_t, and char32_t also exist on all platforms.
Fixed-width integral types
These must be included first with #include <cstdint>.
| Signed | Unsigned | Width |
|---|---|---|
int8_t |
uint8_t |
exactly 8 |
int16_t |
uint16_t |
exactly 16 |
int32_t |
uint32_t |
exactly 32 |
int64_t |
uint64_t |
exactly 64 |
size_t is the optimal type for indexing into an array.
Strings
These must be included first with #include <string>.
All strings extend std::basic_string<T>. std::wstring is a Unicode string, using wchar_t as the character type. std::string is an ASCII string, using char as the character type.
Constants
There are a few different meanings of constant in C++:
constmarks a value as immutable, preventing it from being modified.constexprmarks a value as being calculated at compile-time.* constindicates a constant pointer. The data behind the pointer can be modified, but the pointer itself cannot.fn() constmarks a constant method, preventing class members from being modified.
const int v = 2*3; // value is immutable. constexpr int v = 2*3; // value is calculated at compile time. int fibonacci(const int n); // function will not modify its argument. int List::size() const; // method will not modify any members.
Functions
A function can be a member of a class. The class name is part of the signature.
char& String::operator[](int index);
Collections
Vector
A resizeable homogeneous array, defined as std::vector in the vector library.
vector<unsigned int> list = { 1, 2, 3 };
list.at(0);
list[0];
list.size();
Map
Hashmaps are provided as std::unordered_map in the unordered_map library.
unordered_map<string, string> registry = {};
registry.insert({"key", "value"});
string v = registry["key"];
References
int x = 1; // x is 1 int& r = x; // r is a reference to x r = 2; // x is 2
Passing by reference
Values can be passed by reference by adding a & character as a suffix to the argument in the function signature:
#include <iostream>
#include <vector>
using namespace std;
int sum_list(vector<int>& list) {
int sum = 0;
for (int element : list) {
sum += element;
}
return sum;
}
int main() {
vector<int> list = { 1, 2, 3 };
cout << sum_list(list) << "\n";
}
rvalue reference
An rvalue (or ‘temporary’) is a value that is about to be destroyed. An rvalue reference, identified by T&&, refers to an rvalue that can be modified. It allows a value to be passed to a function with move semantics, rather than the default behaviour of copying the value and then immediately deleting the original instance.
int&& a = 5;
Pointers
Creating a pointer
Pointers are created with the & address-of syntax.
int x = 2; int* p = &x; *p = 3;
Pointer arithmetic
A pointer can be advanced to point to the following item of a sequence with the ++ operator.
Null pointer
The null pointer is called nullptr, and represents the absence of a value. It is used as the terminator for null-terminated strings.
There is only one nullptr shared by all pointer types.
Allocation
Objects can be allocated onto the heap with new, and deallocated with delete.
int* values = new int[10]; delete values;
Classes
Class members are private by default.
class Stack {
private:
uint8_t p;
uint8_t mem[256];
public:
Stack();
};
Stack::Stack() : p{0}, mem{} {
}