⚙️ 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 |