Раздел справочника

Стандартная библиотека C++

Стандартная библиотека C++ предоставляет контейнеры, алгоритмы, итераторы, строки, умные указатели, потоки ввода-вывода, средства работы со временем, файловой системой, многопоточностью и набор утилит для безопасного выражения владения, отсутствующих значений и вариантных типов.

Overview

Зачем использовать стандартную библиотеку

Стандартная библиотека C++ закрывает большую часть повседневных задач: хранение данных, сортировку, поиск, работу со строками, временем, файлами, потоками и ресурсами. В современном C++ код обычно строится вокруг стандартных типов владения и контейнеров, а не вокруг ручного управления памятью.

Практическое правило: сначала выбирай стандартный контейнер или утилиту, и только потом пиши собственную структуру данных. Например, std::vector почти всегда лучше ручной пары new[] / delete[].

Контейнеры

Хранят объекты и управляют памятью: vector, array, deque, map, unordered_map.

Алгоритмы

Работают поверх диапазонов и итераторов: сортировка, поиск, копирование, трансформация, подсчёт и проверка условий.

RAII-утилиты

Умные указатели, lock-объекты и файловые потоки освобождают ресурсы в деструкторах.

Containers

Контейнеры

Контейнеры стандартной библиотеки управляют хранением элементов, выделением памяти и базовыми операциями вставки, удаления и доступа. Выбор контейнера влияет на сложность операций, locality данных, стабильность ссылок и итераторов.

Контейнер
Когда выбирать
Важное свойство
std::vector
Последовательность элементов, частый обход, добавление в конец.
Непрерывная память, хорошая cache locality.
std::deque
Нужны быстрые вставки и удаления с двух концов.
Не гарантирует единый непрерывный блок памяти.
std::map
Нужен отсортированный порядок ключей.
Операции обычно логарифмические.
std::unordered_map
Нужен быстрый поиск по ключу без сортировки.
Производительность зависит от хэша и количества коллизий.

Algorithms

Алгоритмы

Заголовок <algorithm> содержит обобщённые алгоритмы, которые работают с диапазонами через итераторы. Они позволяют отделить логику обработки данных от конкретного контейнера.

#include <algorithm>
#include <vector>

std::vector<int> values{5, 1, 9, 2, 7};

std::sort(values.begin(), values.end());

auto it = std::lower_bound(values.begin(), values.end(), 7);
bool found = it != values.end() && *it == 7;

Iterators

Итераторы и диапазоны

Итератор — объект, который указывает на элемент диапазона и позволяет переходить к другим элементам. Алгоритмы стандартной библиотеки обычно принимают пару итераторов: начало и конец диапазона.

Input iterator

Последовательное чтение значений. Подходит для однонаправленного прохода по данным.

Forward iterator

Позволяет многократно проходить диапазон в прямом направлении.

Bidirectional iterator

Поддерживает движение вперёд и назад, например у std::list.

Random access iterator

Поддерживает быстрый доступ по смещению, например у std::vector.

Важно: разные контейнеры имеют разные правила инвалидирования итераторов. Например, расширение std::vector может переместить буфер и сделать старые указатели и итераторы недействительными.

Strings

Строки

std::string хранит последовательность символов и управляет памятью автоматически. Для передачи строки без владения часто используют std::string_view, если вызываемый код не должен продлевать время жизни данных.

#include <string>
#include <string_view>

bool starts_with_prefix(std::string_view text, std::string_view prefix) {
    return text.starts_with(prefix);
}

std::string make_message(int code) {
    return "status code: " + std::to_string(code);
}

Memory

Память и владение

Современный C++ выражает владение ресурсами через объекты. Для динамических объектов используются умные указатели, а для массивов и буферов — контейнеры. Это уменьшает количество ручного освобождения памяти и делает API понятнее.

Практическое правило: не используй std::shared_ptr по умолчанию. Если владелец один, выбирай std::unique_ptr. Если объект хранится в контейнере, часто достаточно самого контейнера.

Utilities

Утилиты общего назначения

Утилитные типы помогают явно описывать состояние API: значение может отсутствовать, результат может быть одним из нескольких типов, функция может возвращать пару значений, а объект может быть перемещён.

I/O

Ввод-вывод

Библиотека ввода-вывода C++ построена вокруг потоков. Файловые потоки управляют дескрипторами через RAII: файл закрывается при уничтожении объекта потока.

#include <fstream>
#include <string>

std::string read_first_line(const char* path) {
    std::ifstream file(path);

    std::string line;
    std::getline(file, line);

    return line;
}

Time & filesystem

Время и файловая система

<chrono> предоставляет типобезопасную работу со временем, длительностями и часами. <filesystem> позволяет переносимо работать с путями, директориями, статусом файлов и обходом дерева каталогов.

#include <chrono>
#include <filesystem>

namespace fs = std::filesystem;

bool is_regular_non_empty_file(const fs::path& path) {
    return fs::is_regular_file(path) && fs::file_size(path) > 0;
}

auto now = std::chrono::steady_clock::now();

Concurrency

Потоки и синхронизация

Стандартная библиотека содержит базовые средства многопоточности: потоки, mutex, lock-объекты, condition variables, futures и атомарные операции. В многопоточном коде особенно важно избегать гонок данных.

Важно: если два потока обращаются к одному объекту, хотя бы один поток пишет, и нет синхронизации, возникает data race. В C++ это неопределённое поведение.

Examples

Небольшие примеры

Подсчёт частот через unordered_map

#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

std::unordered_map<std::string, int>
count_words(const std::vector<std::string>& words) {
    std::unordered_map<std::string, int> result;

    for (std::string_view word : words) {
        ++result[std::string(word)];
    }

    return result;
}

std::unordered_map удобен, когда нужен быстрый поиск и обновление значения по ключу.

Фильтрация через алгоритмы

#include <algorithm>
#include <vector>

std::vector<int> only_positive(std::vector<int> values) {
    auto new_end = std::remove_if(
        values.begin(),
        values.end(),
        [](int x) { return x <= 0; }
    );

    values.erase(new_end, values.end());
    return values;
}

Идиома erase-remove удаляет элементы из последовательного контейнера после перестановки неподходящих значений в конец.