C++
Статьи о C++: от прагматичных основ языка и регулярных типов до низкоуровневой производительности, работы с кэшем и «ненормальных» трюков с компилятором.
- C++
Что делают new и delete
Чем выражения new/delete в C++ отличаются от malloc/free: вызов конструктора и деструктора, оператор new/delete и работа с сырой памятью — с разбором ассемблера.
- C++
Как работает vtable
Как компилятор C++ реализует виртуальные функции: скрытый указатель vptr, таблица vtable и динамическая диспетчеризация — с ручной реализацией на указателях на функции.
- C++
Ассоциативные контейнеры STL
Ассоциативные контейнеры STL: set, map, multiset и multimap — чем отличаются, когда ключи уникальны, а когда повторяются, с короткими примерами.
- C++
Компромиссы кучи и стека
Куча против стека: детерминированность, фрагментация, размер бинарника и потребление памяти — почему в играх и на консолях выгодно минимизировать кучу.
- C++
Как «ужать» мегаполис до размеров iPhone 4
Инженерная изнанка мобильной SimCity BuildIt: как затолкали десктопный ситибилдер в 100–300 МБ памяти айфона — server-authoritative экономика на таймерах, «глупый» клиент-терминал, агрессивный батчинг и текстурные атласы, TBDR-рендер с превью-секторами, вырезанная симуляция с пробками-спрайтами, электричество через Capacity − Demand и рынок-«доска объявлений». Плюс история питерской студии EA SPB.
- C++
Путеводитель по чужим STL
Обзор альтернативных «стандартных» библиотек C++ из игровых студий и больших контор: EASTL и её best practices, LLVM SmallVector/DenseMap, Folly и устройство fbstring (SSO, eager copy, COW и связка с jemalloc), boost flat_map, сериализуемые контейнеры Zmeya, Stlab от Adobe и value-oriented programming — зачем каждая появилась и где об неё можно больно удариться.
- C++
C++101 (Ч.1)
Каталог из ~100 идиом и приёмов C++, выросший из раздела Game++. Часть 1: ресурсы и компиляция — RAII, scope guard, copy-and-swap, smart pointer, copy-on-write, Pimpl, interface class, include/inline/export guard, CRTP, Barton-Nackman, EBO и metafunction.
- C++
C++101 (Ч.2)
Часть 2: метапрограммирование и шаблоны — traits, tag dispatching, int-to-type, type selection, SFINAE и enable-if, member detector, policy-based design, type erasure, thin template, named template parameters, expression templates и result_of, плюс именованные конструкторы и base-from-member.
- C++
C++101 (Ч.3)
Часть 3: инициализация, полиморфизм и контейнеры — calling virtuals during init, NVI и thread-safe interface, acyclic visitor, covariant return types, virtual friend function, algebraic hierarchy, polymorphic value types, функторы, iterator pair, generic container, erase-remove, safe bool и attorney-client.
- C++
C++101 (Ч.4)
Часть 4: дружба, память объектов и современный C++ — non-member non-friend, SOO/SSO, prohibiting heap, execute-around pointer, temporary proxy, nullptr, move constructor, boost mutant, deprecate and delete, function poisoning, rule of zero/three/five, most vexing parse, pass-key и spaceship-оператор.
- C++
Как игровой GUI пишут заново (Ч.2)
Продолжение: архитектура игрового UI по шести независимым осям — расположение относительно мира (diegetic / HUD / meta / spatial / narrative, от Metroid Prime и Dead Space до Spec Ops и Hellblade), функция, хранение в памяти (scene graph, flat list, immediate mode, ECS), поток данных (MVC/MVVM, reactive, unidirectional), раскладка (constraint, flexbox, anchors, RIMD) и рендер (canvas, layer, SDF, GPU-driven). Часть 2.
- C++
Почему игровой GUI пишут заново (Ч.1)
Архитектура игрового UI и почему её переписывают из проекта в проект: дерево контролов как Composite, свойства с рефлексией, развязка с игровым кодом через биндинги, шаблоны-прототипы задолго до Unity Prefab, три уровня обработчиков, хит-тест по форме, синхронные сообщения, раскладка и 9-slice, целочисленные координаты, Bridge поверх рендера, стили как CSS, боль локализации, SDF-шрифты и диегетический UI (Dead Space, Doom, Metro). Часть 1.
- C++
Менеджер ресурсов
Почему менеджер ресурсов — это не синглтон, а целая подсистема движка: идентичность ресурса как пара «источник + параметры», кэш на слабых ссылках с LRU, явные и неявные параметры, точечная перезагрузка и hot-reload, восстановление после device lost от пулов D3D9 до DX12/Vulkan, общая шаблонная база менеджеров и смена настроек графики без рестарта — на примерах Unreal, Unity, Source, id Tech, Godot, No Man's Sky и Cyberpunk.
- C++
Архитектурные компромиссы в разработке игр
Большой разбор архитектурных паттернов и компромиссов в геймдеве: слои, метаслои, подсистемы, конвейер, микроядро и blackboard на примерах Source, CryEngine, Unreal, id Tech и Naughty Dog; стратегии проектирования, ось push vs pull, скриптовые языки и переосмысление GoF в современном игровом C++.
- C++
Непослушный using
Почему using namespace и ADL делают поиск имён в C++ непредсказуемым: argument-dependent lookup и operator<<, перехват std локальной подменой, проверка пригодности функции (function viability), ранги неявных преобразований и почему =delete-функции участвуют в overload resolution как полноценные кандидаты.
- C++
Простой поиск имён в C++
Простой (неквалифицированный) и квалифицированный поиск имён в C++: сосуществование пространства имён и локальной переменной, скрытие имён и целых перегрузок при наследовании, неоднозначность ромбовидного наследования, правило using namespace при квалифицированном поиске и исторические различия GCC, Clang и MSVC.
- C++
Компиляторы тоже путаются в именах
Поиск имён в C++: идентификаторы, unqualified-id, qualified-id, template-id и «терминальное имя», история ADL (Koenig lookup), двухфазный поиск в шаблонах и почему GCC, Clang и MSVC исторически вели себя по-разному.
- C++
Лишние вычисления
Как спекулятивное выполнение и предсказание ветвлений взаимодействуют с подсистемой памяти: почему branchless-код не всегда быстрее, цена ошибки предсказания против задержек памяти, бинарный поиск и бенчмарки на Jaguar (PS4).
- C++
Мифы, суеверия и народные мудрости в разработке игр
Разбор 12 распространённых «истин» геймдева на C++ — где миф, где суеверие, а где народная мудрость: культ чистого C, «плохой хороший билд», цена исключений и RTTI, умные указатели и STL-контейнеры, полиморфизм, inline-ассемблер, template bloat, преждевременная оптимизация и проклятье пятничного коммита.
- C++
Зоопарк строк в вашем C++ коде?
Большой обзор строковых типов C++ как зоопарка зверей: char* и char[N], строковые литералы, std::string и SSO, string_view, pmr::string, QString, NSString, std::wstring, frame-строки, FString из Unreal, StringAtom и интернирование, COW-строки и StringID на хеше — и где какой тип уместен в игровых движках.
- C++
Хороший, плохой, цветной и быстрый
Ненормальные аллокаторы памяти из практики: аллокатор с отслеживанием времени жизни объектов для поиска утечек, рандомизирующий (chaos) аллокатор для стресс-теста долгоживущих систем, «цветной» аллокатор для изоляции подсистем (на примере Deathloop) и быстрый TLSF — с диаграммами и бенчмарком по циклам процессора.
- C++
Сам себе breakpoint
Как устроены программные и аппаратные точки останова: подмена байта на int 3 (0xCC), отладочные регистры x86-64 DR0–DR7 и формат DR7, условные, функциональные и временные бряки, watchpoint на запись через GetThreadContext, «буферная канарейка» и кнопка hardware breakpoint прямо в редакторе игры на ImGui.
- C++
Я отклоняю комиты с использованием кучи и прошу коллег переписать такую логику
Опыт разработки больших игр на C++ без кучи: чем опасны динамические аллокации на консолях и мобилках (фрагментация, деградация malloc, отказ в сертификации) и чем их заменить — контейнеры фиксированного размера gtl::vector<T,N>, etl/FastDelegate вместо std::function, CRTP и статический полиморфизм на std::variant, пулы объектов и placement new.
- C++
Game++. Performance traps
Финал серии Game++: типичные ловушки производительности C++ — лишние аллокации, коварный RVO, тяжёлый std::function-колбэк, дорогие строковые идентификаторы, приближённый синус, медленное деление, цена промахов кеша, std::pair/tuple и расплата за виртуальность в math-структурах — с бенчмарками quick-bench и историями из прода.
- C++
Game++. while (!game(over))
Стоит ли писать свой игровой движок: зачем и надо ли, что такое движок и что он умеет — игровой цикл, ввод, графика, ассеты, аудио, физика, скрипты и конфиги, сеть, AI, UI и архитектура (библиотечный подход, GodObject, ECS), плюс тулзы — с кодом, ссылками на библиотеки и личным опытом.
- C++
Game++. Patching patterns
Паттерны проектирования в играх: что осталось от «синей книги» GoF и какие прижились именно в игрострое — Command, State и FSM с pushdown-стеком, Flyweight и instancing, Observer и EventBus, Dirty Flag, Update Layers и GOAP — с кодом, схемами и применением.
- C++
Game++. Work hard
Модели параллелизма в игровых движках: shared/separate/shadow state, воркеры и пул потоков, stateless-воркеры (Assassin's Creed, Factorio), цепочки воркеров и неблокирующий IO, файберы Naughty Dog и библиотека marl — с диаграммами, кодом и бенчмарками загрузки.
- C++
Game++. Heap? Less
Как в играх избавляются от аллокаций в куче: пять областей памяти, стек против кучи, детерминизм и фрагментация, RVO/NRVO, локальные inplace-строки и pmr::string, ad-hoc полиморфизм на std::variant, и реальные оптимизации vector/map/string через monotonic_buffer_resource и профайлер.
- C++
Почему игродев остаётся на C++17
Почему игровые студии не спешат с C++20: auto и +10-15% к времени компиляции, лучший в мире отладчик Visual Studio, экономика билдферм и тулов, недоверие к STL и Boost, отсутствие автотестов и немасштабируемость отладки.
- C++
Game++. Unpacking containers
Специализированные контейнеры в движках: fixed array и матрицы, linear/stable/sparse/packed/static/small/dirty/buddy vector, deque и bcdeque, bounded_priority_deque, intrusive list, octree и quadtree, object_pool, ring buffer, cached_hashtable, handle_container и slot_container — устройство, схемы и применение.
- C++
Game++. Building arcs
Архитектуры игровых движков и закон Конвея: унитарная (Big Ball of Mud) у Unity, многоуровневая в Unreal Engine, микроядерная в CryEngine и O3DE, data-driven в Dagor, монолитная в X-Ray и микромодульная в Godot.
- C++
Game++. run, thread, run…
Многопоточность в играх: проблемы блокировок (deadlock, голодание потоков, инверсия приоритетов на примере Cyberpunk 2077 и Crysis), модель памяти C++11, lock-free и атомики, спинлоки с backoff, пул потоков и система задач, hitching и read-write mutex.
- C++
Game++. Juggling STL algorithms
Почему алгоритмы STL — это «разговорный» C++: показывают Что вы делаете, а не Как; убирают ошибки границ, пустых коллекций и «размазанного перфа». История EASTL, итераторы и back_inserter, кеширование шейдеров через set_difference и большая шпаргалка по алгоритмам.
- C++
Game++. Dancing with allocators
Большой разбор аллокаторов памяти в играх: linear, step-back, frame, stack, pool, free list, arena, segregated, buddy, thread-cache, fibonacci, compacting, hot/cold splitting и TLSF — с кодом, схемами и бенчмарком.
- C++
Game++. Cooking vectors
Как устроены векторы в движках и чем за них платят: рост ёмкости и фрагментация памяти, одномерная против каскадной композиции, std::array, static_vector на стеке, hybrid_vector с SSO-подобной оптимизацией и подводные камни pmr-аллокаторов у вендоров.
- C++
Game++. String interning
String interning (пул строк) в движках: одна копия строки на все ссылки, интернирование литералов в clang/GCC и почему трюк ломается на Xbox, опасность сравнения через ==, борьба с фрагментацией памяти и простая реализация xstring на хешах с подсчётом ссылок.
- C++
Как засунуть слона в чемодан
Уровни оптимизации при портировании игр на слабое железо: архитектура, алгоритмы и код. История про дорогую проверку экранирования строк — от наивного цикла к версии без ветвлений, lookup-таблице и SIMD на _mm_movemask_epi8.
- C++
Spears & bits
Упаковка булей в биты: std::bitset, std::vector<bool>, наивный байтовый массив и решение из CryEngine, бенчмарки с выбросами на 32/64/128, промахи предсказателя переходов и финальная SSE-векторизация на _mm_movemask_epi8.
- C++
Task-based мышление в игровых движках
Основные шаблоны системы задач в движках: вынос movement, физики, скриптов, поиска пути, анимаций, рендеринга и ввода-вывода в отдельные потоки, группировка задач, обмен сообщениями и сравнение простой задачи, менеджера потоков и менеджера задач.
- C++
Тяжёлый H[header]
Как снижали время сборки большого C++-проекта с 15:32 до 5:16: тяжёлые шаблонные хедеры, инстанцирование, forward declaration, precompiled headers, PIMPL, windows.h и отключение анализаторов и LTO — с таблицами времени сборки заголовков.
- C++
Шеф, всё пропало
Продолжение «Феди, дичи»: 16 пятничных багов из реальных движков — выход за границы массива, утечки дескрипторов на Switch, memset по нетривиальному типу, =! вместо != и alloca в цикле.
- C++
Просто не копируй это
Передача по значению против const&, скрытые аллокации на строках и векторах, reserve и реальная просадка до 10 FPS — всё с бенчмарками.
- C++
Строки в игровых движках
C-строки и NTBS, std::string и SSO, string_view, sized/pool/arena-строки, shared string, идентификаторы и SIMD-парсинг — как со строками работают в движках.
- C++
Каков C++ в gamedev'е?
На каких уровнях C++ живёт в движке: hardcore-числодробилки, «обычный» C++ со скриптами и хотрелоадом, и мета-уровень с RTTI, рефлексией и кодогенерацией.
- C++
Магия swizzle из шейдеров в C++
Как реализовать swizzle (vec.xxy, vec.zx) в C++ через union и шаблоны — без накладных расходов по памяти и быстрее glm и CxxSwizzle.
- C++
Федя, дичь
Коллекция диких багов из реальных движков: пропущенная точка с запятой в Unity, memset, выкинутый компилятором, гонки на битовых полях в CryEngine, most vexing parse и ещё десяток.
- C++
Важны ли компилятору имена
Как компилятор отвечает на два главных вопроса — что значит имя и какой вариант правильный: поиск имён и разрешение перегрузок, сосуществование имён разных категорий, конфликты function/namespace/enum и почему за всем этим стоит name mangling из 80-х.
- C++
И снова ограничения
Принципиальные ограничения концептов в C++: запрет рекурсии в определении концепта и невозможность навесить requires на сам концепт, формы записи requires, применение концептов к классам, методам, конструкторам и локальным переменным, частичный порядок и атомарные ограничения.
- C++
Иерархия концептов в C++
Как компилятор выбирает перегрузку среди нескольких подходящих шаблонов через подчинение ограничений (subsumption) и частичный порядок: синтаксическая идентичность важнее логической эквивалентности, иерархия концептов итераторов STL и где сложные иерархии вредят ясности кода.
- C++
История концептов в C++
Как концепты прошли путь от амбициозных семантических предложений конца 1990-х (рефлексивность, симметричность, транзитивность) и «тяжёлых» концептов почти в C++11 до прагматичной модели Concepts Lite в C++20 — проверки синтаксиса вместо гарантий поведения.
- C++
Концепты и ограничения в C++
Концепты и ограничения (requires) как замена SFINAE и enable_if: явные контракты к типам прямо в сигнатуре, requires как часть сигнатуры, requires-выражения, простые и сложные ограничения и static_assert.
- C++
Перегрузки в C++
Перегрузки не как синтаксический сахар, а как механизм обобщённого программирования: алгоритм прежде типов, возведение в степень через квадрат, хорошие и плохие наборы перегрузок и критика дизайна std::filesystem.
- C++
Обобщения в C++ (часть 2)
Продолжение главы 1: идентичность и равенство объектов, процедуры и стек вызовов, соглашения о вызовах и категории in/out/in-out, вычислительная база от ENIAC до AMX и регулярность типов как практическое руководство по проектированию.
- C++
Обобщения в C++ (часть 1)
Опубликованная глава 1: C++ как способ говорить о мире через сущности, виды и роды, значения и их битовое представление, уникальность представления и равенство, чистые (регулярные) функции и объекты как договор между программистом, компилятором и машиной.
- C++
Обобщения, значения и объекты в C++
Сущности, виды и роды, значения и их представление, объекты, процедуры, вычислительная база и регулярность — фундамент языка.
- C++
Торопиться не надо… (Про спинлоки)
Реализации спинлоков — от наивной TAS до тикет-спинлока — с бенчмарками, кэш-миссами и нюансами приоритезации потоков.
- C++
Cache pollution? Запасайтесь тестами
Как кэш, ассоциативность, когерентность и выравнивание данных влияют на производительность — с бенчмарками.
- C++
Имя enum'a C++ в рантайме
Как достать имя типа и значения enum'а в рантайме без RTTI — через __PRETTY_FUNCTION__, шаблоны и constexpr-магию.
- C++
Когда private, но очень хочется public
Как тестировать приватные члены C++-класса без правки хедеров: от friend-ов и #define private public до шаблонного хака.
- C++
Зачем в Switch SDK три разных sin?
Как при портировании игр обнаружились три реализации sin — и что показал дизасм для разных уровней оптимизации.