Cheatsheets

Personal collection of cheatsheets.

C++

C++ is a general-purpose programming language created as an extension of the C programming language.

Index

Compilers

A compiler is a computer program that translates computer code written in one programming language (the source language) into another language (the target language). It is primarily used for programs that translate source code from a high-level programming language to a low-level programming language (e.g. assembly language, object code, or machine code) to create an executable program.

GCC

GCC (GNU Compiler Collection) is a collection of compilers that support various programming languages, hardware architectures, and operating systems by the GNU project.

Clang

Clang is a compiler front end and tooling infrastructure for languages in the C language family (C, C++, Objective C/C++, OpenCL, and CUDA) by the LLVM project.

MSVC

MSVC (Microsoft Visual C++) is a compiler for the C, C++, C++/CLI and C++/CX programming languages by Microsoft.

Libraries

A library is a collection of resources used by programs. These resources may include code, data, templates, documentation, etc.

There are 2 types of libraries, static and dynamic.

When linking is performed during the creation of an executable or an object file, it is known as static linking (early binding). In this case, the linking is usually done by a linker, but may also be done by the compiler.

When linking is performed while a program is being loaded (load time) or executed (runtime), it is known as dynamic linking (late binding).

Dynamic libraries have 2 types of linking.

List of libraries.

Library
args
Dear ImGui

Dependencies

Managing include files dependencies is crucial for maintaining clean, efficient, and scalable code.

IWYU

IWYU (Include What You Use) is a strategy (and a tool) for managing include directives where the core idea is every file should include only the headers it directly uses.

✅ Pros

❌ Cons

#pragma once

#include <string>
#include <vector>

class Bar; // Forward declaration.

class Foo {
public:
    void setName(const std::string& name);
    void setData(const std::vector<int>& data);
    void setBar(const Bar& bar);

private:
    std::string name;
    std::vector<int> data;
    Bar* bar;
};

PCH

PCH (Precompiled Header) is a file (typically pch.h) that contains the compiled version of commonly included headers. Instead of parsing and compiling the same headers repeatedly for every source file, the compiler does it once and reuses the result.

✅ Benefits

❌ Downsides

#ifndef PCH_H
#define PCH_H

#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
// ...

#endif // PCH_H

Null

std::nullptr

std::nullptr (C++11) is the null pointer literal.

std::nullptr_t

std::nullptr_t (C++11) is the type of the null pointer literal nullptr.

Pointers

std::unique_ptr

std::unique_ptr (C++11) is a smart pointer that owns and manages another object (heap-allocated memory) via a pointer and subsequently disposes of that object when the unique_ptr goes out of scope.

#include <memory>

class Foo
{
public:
    void Bar(){}
};

void Process(const Foo& foo)
{
    // ...
}

void Run()
{
    std::unique_ptr<Foo> foo = std::make_unique<Foo>();

    // Call a method on the object.
    foo->Bar();

    // Pass the reference to a function.
    Process(*foo);

    // Deleted automatically when function block goes out of scope.
}

int main(int argc, char** argv)
{
    Run();
    return 0; 
}

std::shared_ptr

std::shared_ptr (C++11) is a smart pointer that retains shared ownership of an object through a pointer. Several shared_ptr objects may own the same object. The object is destroyed and its memory deallocated when the last remaining shared_ptr owning the object is destroyed.

#include <memory>

class Foo
{
public:
    void Bar(){}
};

void Process1(std::shared_ptr<Foo> foo)
{
    // ...
}

void Process2(std::shared_ptr<Foo> foo)
{
    // ...
}

int main(int argc, char** argv)
{
    std::shared_ptr<Foo> foo = std::make_shared<Foo>();

    Process1(p);
    Process2(p);

    return 0;
}

std::weak_ptr

std::weak_ptr (C++11) is a smart pointer that holds a non-owning (weak) reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

Casting

Casting is the action of explicitly converting a value from one type to another.

static_cast

static_cast converts between types that the compiler knows how to convert.

int i = 42;
float f = static_cast<float>(i);

Derived* d = new Derived();
Base* b = static_cast<Base*>(d); // Upcast.

dynamic_cast

dynamic_cast converts pointers and references to classes up, down, and sideways along the inheritance hierarchy.

Base* b = new Derived();
Derived* d = dynamic_cast<Derived*>(b); // Downcast.

const_cast

const_cast converts between types with different const and volatile qualifications.

const char* constStr = "hello";
char* str = const_cast<char*>(constStr); // Only safe if was not originally const.

reinterpret_cast

reinterpret_cast converts between types by performing bitwise reinterpretation of memory.

char* c = reinterpret_cast<char*>(uint8Pointer);
uint64_t value = reinterpret_cast<uint64_t>(pointer); // pointer → int

Concurrency

std::thread

std::thread (C++11) provides a standard way to write multithreaded programs accross all platforms abstracting the code from other threading APIs like POSIX pthreads or Windows threads.

#include <iostream>
#include <thread>

void Task1()
{
    for (int i = 0; i < 100; i++)
    {
        std::cout << "(Task, 1)";
        std::cout << " (Thread ID, " << std::this_thread::get_id() << ")";
        std::cout << " (Loop, " << i << ")";
        std::cout << std::endl;
    }
}

void Task2()
{
    for (int i = 0; i < 100; i++)
    {
        std::cout << "(Task, 2)";
        std::cout << " (Thread ID, " << std::this_thread::get_id() << ")";
        std::cout << " (Loop, " << i << ")";
        std::cout << std::endl;
    }
}

int main(int argc, char** argv)
{
    std::thread worker1(Task1);
    std::thread worker2(Task2);
    
    worker1.join();
    worker2.join();
    
    return 0;
}

std::async

std::async (C++11) provides a way to run a function asynchronously (potentially in a separate thread) and returns a std::future that will eventually hold the result of that function call.

Policies:

#include <future>
#include <iostream>
#include <thread>

void Task(std::string name, int count)
{
    for (int i = 0; i < count; i++)
    {
        std::cout << "(Task, " << name << ")";
        std::cout << " (Thread ID, " << std::this_thread::get_id() << ")";
        std::cout << " (Loop, " << i << ")";
        std::cout << std::endl;
    }
}

int main(int argc, char** argv)
{
    std::future<void> future1 = std::async(std::launch::async, Task, "Task1", 100);
    std::future<void> future2 = std::async(std::launch::async, Task, "Task2", 200);

    future1.get();
    future2.get();

    return 0;
}

Comparing thread-based programming (std::thread) and task-based programming (std::async).

State-of-the-art thread schedulers employ system-wide thread pools to avoid oversubscription, and they improve load balancing across hardware cores through workstealing algorithms. The C++ Standard does not require the use of thread pools or work-stealing, and, to be honest, there are some technical aspects of the C++11 concurrency specification that make it more difficult to employ them than we’d like. Nevertheless, some vendors take advantage of this technology in their Standard Library implementations, and it’s reasonable to expect that progress will continue in this area. If you take a task-based approach to your concurrent programming, you automatically reap the benefits of such technology as it becomes more widespread. If, on the other hand, you program directly with std::threads, you assume the burden of dealing with thread exhaustion, oversubscription, and load balancing yourself, not to mention how your solutions to these problems mesh with the solutions implemented in programs running in other processes on the same machine.

std::future

std::future (C++11) provides a way to access the result of asynchronous operations.

std::promise

std::promise (C++11) provides a way to store a value or an exception that is later acquired asynchronously via a std::future created by the std::promise.

References