⚙️ C++

Полный справочник: типы, указатели и ссылки, управление памятью (RAII), классы, шаблоны, STL, лямбды, потоки, современные стандарты C++11–23 и сборка.

Шпаргалки · Программирование · #c++ #cpp #systems #stl

Сборка и инструменты

g++ -std=c++20 -Wall -Wextra -O2 main.cpp -o app          clang++ -std=c++20 main.cpp
g++ -g -fsanitize=address,undefined main.cpp               # отладка и поиск ошибок памяти
cmake -S . -B build && cmake --build build                  # CMake

Менеджеры пакетов: vcpkg, Conan. IDE: CLion, Visual Studio, VS Code. Статический анализ: clang-tidy, cppcheck. Форматирование: clang-format. Стандарты: C++11, 14, 17, 20, 23.

Минимальная программа

#include <iostream>
int main() {
    std::cout << "Привет\n";
    return 0;
}

#include подключает заголовки; using namespace std; в заголовках не пишите.

Типы данных

Группа Типы
Целые short, int, long, long long, unsigned, <cstdint>: int32_t, uint64_t, size_t
Дробные float, double, long double
Символы и логика char, wchar_t, char8_t, bool
Автоматический вывод auto, decltype
Строки и контейнеры std::string, std::string_view, std::vector<T>
int n = 5; double d = 3.14; bool ok = true; auto x = 10;
const int N = 100;  constexpr int sq(int v) { return v * v; }     // вычисляется на этапе компиляции
int a[3] = {1, 2, 3};   std::array<int, 3> b{1, 2, 3};
static_cast<int>(3.9);     // безопасное приведение; избегайте C-стиля (int)x
auto [id, name] = std::pair{1, "a"};                                // structured bindings (17)

Указатели, ссылки, память

int v = 1;
int* p = &v;     *p = 2;                 // указатель: адрес
int& r = v;      r = 3;                  // ссылка: псевдоним, всегда привязана
const int& cr = v;                        // не копирует, не меняет
int* q = nullptr;                         // вместо NULL

Умные указатели (RAII) вместо new/delete:

auto u = std::make_unique<User>("anna");           // единоличное владение
auto s = std::make_shared<User>("anna");           // общее владение (счётчик ссылок)
std::weak_ptr<User> w = s;                          // не продлевает жизнь, разрывает циклы

RAII: ресурс (память, файл, мьютекс) захватывается в конструкторе и освобождается в деструкторе автоматически.

Правила: не возвращайте ссылки на локальные объекты, не выходите за границы (at() проверяет), не используйте освобождённую память. Правило нуля / пяти: если не нужен собственный деструктор, не пишите специальные методы; если нужен, определите все пять (деструктор, копирование, перемещение).

Строки

std::string s = "Привет";
s.size(); s.empty(); s += "!"; s.substr(1, 3); s.find("и"); s.replace(0, 1, "П"); s.c_str();
std::to_string(42); std::stoi("42"); std::stod("3.14");
std::string_view sv = s;                       // без копирования
std::format("{} = {:.2f}", name, 3.14159);      // C++20

Юникод в std::string хранится как UTF-8 байты: size() не равно числу символов.

Операторы и управление

if (x > 0) {} else if (x == 0) {} else {}
if (auto it = m.find(k); it != m.end()) { }          // инициализация в if (17)
switch (n) { case 1: break; default: break; }
for (int i = 0; i < 3; ++i) {}
for (const auto& e : vec) {}                          // по ссылке: без копий
for (auto& [k, v] : map) {}
while (cond) {}  do {} while (cond);
x ? a : b;  &&  ||  !  <=>  (трёхстороннее сравнение 20)

Функции и лямбды

int add(int a, int b = 0) { return a + b; }
void inc(int& x) { ++x; }                              // изменяет вызывающего
void show(const std::string& s) {}                      // без копии
template <typename T> T mx(T a, T b) { return a > b ? a : b; }
template <std::integral T> T twice(T x) { return x * 2; }   // concepts (20)

auto f = [](int x) { return x * x; };
int base = 10;
auto g = [base](int x) { return x + base; };            // захват по значению
auto h = [&base](int x) { base += x; };                  // по ссылке
std::function<int(int)> fn = f;

Классы

class User {
public:
    User(std::string name, int age) : name_(std::move(name)), age_(age) {}
    virtual ~User() = default;
    const std::string& name() const { return name_; }
    virtual void print() const { std::cout << name_ << '\n'; }
    static int count;
private:
    std::string name_;
    int age_;
};
class Admin final : public User { void print() const override {} };
struct Point { int x{}, y{}; auto operator<=>(const Point&) const = default; };
enum class Color { Red, Green };                          // типобезопасное перечисление

Базовый класс с виртуальными методами обязан иметь виртуальный деструктор. explicit на одноаргументные конструкторы, = delete запрещает операцию, noexcept обещает отсутствие исключений.

STL: контейнеры

Контейнер Применение
std::vector динамический массив (по умолчанию)
std::array фиксированный массив
std::deque очередь с двух концов
std::list двусвязный список
std::map, std::set упорядоченные, дерево, O(log n)
std::unordered_map, std::unordered_set хэш, O(1) в среднем
std::stack, std::queue, std::priority_queue адаптеры
std::optional, std::variant, std::tuple, std::pair составные значения
std::vector<int> v{3, 1, 2};
v.push_back(4); v.emplace_back(5); v.size(); v.reserve(100); v.erase(v.begin());
std::unordered_map<std::string, int> m; m["a"] = 1; m.contains("a"); m.at("a");

STL: алгоритмы и диапазоны

#include <algorithm>
#include <numeric>
std::sort(v.begin(), v.end());            std::sort(v.begin(), v.end(), std::greater<>());
auto it = std::find(v.begin(), v.end(), 2);   std::count_if(v.begin(), v.end(), [](int x) { return x > 1; });
std::transform(v.begin(), v.end(), v.begin(), [](int x) { return x * 2; });
int sum = std::accumulate(v.begin(), v.end(), 0);   std::reverse(v.begin(), v.end());
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x < 0; }), v.end());   // erase-remove
// C++20 ranges
for (int x : v | std::views::filter([](int x) { return x % 2; }) | std::views::transform([](int x) { return x * x; })) {}
std::ranges::sort(v);

Исключения

try { throw std::runtime_error("ошибка"); }
catch (const std::exception& e) { std::cerr << e.what() << '\n'; }
catch (...) { }

Ловите по константной ссылке. Исключения не бросайте из деструкторов. Альтернатива: std::optional, std::expected (23), коды ошибок.

Файлы и потоки

#include <fstream>
std::ifstream in("a.txt"); std::string line; while (std::getline(in, line)) {}
std::ofstream out("b.txt"); out << "текст\n";
std::filesystem::exists("a.txt"); std::filesystem::path p = "dir/a.txt";

Многопоточность

#include <thread>
#include <mutex>
#include <future>
#include <atomic>
std::thread t([] { /* работа */ });   t.join();                // или std::jthread (20): присоединяется сам
std::mutex m;   { std::lock_guard<std::mutex> lock(m); /* защищённая секция */ }
auto fut = std::async(std::launch::async, [] { return 42; });  fut.get();
std::atomic<int> counter{0}; counter.fetch_add(1);

Данные гонки (data race) это неопределённое поведение: защищайте общие данные мьютексом или атомиками. Корутины C++20 (co_await) требуют библиотек поддержки.

Подводные камни

  • Неопределённое поведение: выход за границы, висячие ссылки, переполнение знаковых, неинициализированные переменные.
  • Копирование больших объектов: передавайте по const&, перемещайте std::move.
  • Срез объекта (object slicing) при передаче производного класса по значению.
  • Забытый virtual деструктор.
  • Недействительные итераторы после изменения контейнера.
  • Порядок инициализации членов по объявлению, а не по списку инициализации.

Библиотеки по задачам

Задача Что взять
Общее Boost, Abseil, fmt
GUI Qt, Dear ImGui, wxWidgets
Сеть Boost.Asio, cpp-httplib, libcurl, gRPC, Drogon
JSON nlohmann/json, simdjson, RapidJSON
Логи spdlog
Матрицы Eigen, Armadillo
Графика и игры SDL, SFML, OpenGL, Vulkan, Unreal Engine
Изображения OpenCV
БД SQLite, libpqxx
Тесты GoogleTest, Catch2, doctest
Сборка CMake, Meson, Ninja, Bazel