C++MiddleExperience
Для каких задач C++ является сильным выбором, а где лучше честно выбрать другой язык?
C++ оправдан для систем с жёсткими требованиями к латентности и памяти (HFT, game engines, embedded, компиляторы); для CRUD-сервисов, скриптов и команд без C++-экспертизы лучше Go, Python или Rust.
Когда C++ — правильный выбор
C++ остаётся незаменимым в задачах, где требуется максимальный контроль над памятью и предсказуемая латентность без GC-пауз:
- Системное программирование — ядра ОС, драйверы, гипервизоры (QEMU, KVM). Нулевые накладные расходы на абстракции.
- Game engines — Unreal Engine, id Tech: физика, рендер, аудио требуют детерминированного времени кадра. GC-паузы в 50+ мс неприемлемы.
- HFT и low-latency trading — latency p99 < 1 мкс. Используют
std::atomic, lock-free очереди, memory-mapped файлы. - Embedded без ОС — микроконтроллеры ARM Cortex-M:
-ffreestanding, без стандартной библиотеки, ручное управление стеком. - Компиляторы и runtime-ы — LLVM, V8, CPython написаны на C++. Тонкий контроль над layout структур.
- Мультимедиа и CV — OpenCV, FFmpeg: SIMD-оптимизации через intrinsics (
_mm256_add_ps), векторизация компилятором.
Пример: lock-free очередь для HFT
#include <atomic>
#include <array>
template<typename T, std::size_t N>
class SPSCQueue {
std::array<T, N> buf_;
alignas(64) std::atomic<size_t> head_{0};
alignas(64) std::atomic<size_t> tail_{0};
public:
bool push(const T& val) {
size_t t = tail_.load(std::memory_order_relaxed);
size_t next = (t + 1) % N;
if (next == head_.load(std::memory_order_acquire)) return false;
buf_[t] = val;
tail_.store(next, std::memory_order_release);
return true;
}
bool pop(T& val) {
size_t h = head_.load(std::memory_order_relaxed);
if (h == tail_.load(std::memory_order_acquire)) return false;
val = buf_[h];
head_.store((h + 1) % N, std::memory_order_release);
return true;
}
};
Здесь alignas(64) предотвращает false sharing между ядрами, memory_order_acquire/release даёт корректную синхронизацию без полного барьера.
Когда C++ — плохой выбор
- CRUD-сервисы и API — Go, Python, Kotlin дают в 3–5 раз быстрее time-to-market. Разница в производительности нивелируется сетью и БД.
- Скрипты и автоматизация — Python/Bash на порядок проще. Компиляция и отсутствие REPL замедляют итерации.
- Команда без C++-экспертизы — UB (undefined behavior), висячие ссылки, use-after-free приводят к трудно диагностируемым багам в production.
- Быстрые прототипы ML-моделей — Python + PyTorch достаточно. C++ нужен только для inference-оптимизации (TensorRT, ONNX Runtime).
- Мобильные приложения — Swift/Kotlin дают лучший DX, безопасность памяти, интеграцию с платформой.
Сравнение с ближайшими альтернативами
- Rust — сопоставимая производительность, borrow checker исключает data races и use-after-free на этапе компиляции. Найм сложнее, экосистема меньше, но растёт.
- C — проще, предсказуемее, но нет RAII, шаблонов, умных указателей. Приходится вручную управлять ресурсами.
- Go — GC с паузами <1 мс (Go 1.18+), goroutines. Хорош для сетевых сервисов, плох для real-time задач с жёсткими latency-требованиями.
Подводные камни
- Недооценка стоимости code review и онбординга: junior-разработчик на C++ без опыта создаёт UB-баги, которые воспроизводятся только в release-сборке.
- Игнорирование AddressSanitizer (
-fsanitize=address) и UBSanitizer в CI — утечки памяти уходят в production. - Смешивание C-стиля (
malloc/free, сырые указатели) с C++11+ RAII — ломает exception safety. - Отсутствие единого пакетного менеджера: Conan vs vcpkg vs submodules — нет очевидного стандарта, в отличие от npm или pip.
- Переоценка «нулевой стоимости абстракций»: виртуальные функции,
std::function, исключения добавляют реальные накладные расходы на критических путях. - Забывают про ABI-совместимость: обновление компилятора или флагов может сломать бинарную совместимость между shared libraries.
- Время компиляции больших проектов (Chromium — часы): без precompiled headers, unity builds или clangd LSP разработка тормозит.
What hurts your answer
- Выбирать C++ по популярности, а не по требованиям проекта
- Игнорировать опыт команды, эксплуатацию и стоимость поддержки
- Не называть ситуации, где C++ будет плохим выбором
What they're listening for
- Называет критерии выбора C++
- Учитывает команду, эксплуатацию, стоимость и риски
- Может назвать сценарии, где выбрал бы альтернативу