Senior C++ Developer
12.5K subscribers
1.35K photos
3 videos
607 links
Изучаем C++.

По вопросам сотрудничества: @adv_and_pr

РКН: https://www.gosuslugi.ru/snet/676e9a1e4e740947beca35ba
Download Telegram
Критическая секция

Критическая секция — это участок кода, который должен быть выполнен только одним потоком в определенный момент времени, чтобы избежать гонок данных (race conditions) и сохранить целостность данных. Для обеспечения безопасности в многопоточной среде можно использовать различные механизмы синхронизации, такие как мьютексы (mutexes) и блокировки (locks).

В примере на картинке два потока вызывают функцию someFunction, которая содержит критическую секцию, защищенную мьютексом mtx. Перед выполнением критической секции поток блокирует мьютекс с помощью mtx.lock(), а после выполнения разблокирует его с помощью mtx.unlock(). Это гарантирует, что только один поток может находиться внутри критической секции в определенный момент времени.

Помимо std::mutex, в C++ также существуют другие механизмы синхронизации, такие как std::lock_guard и std::unique_lock, которые упрощают работу с мьютексами и делают код более безопасным.

#для_продвинутых
<unistd.h>

<unistd.h> — это заголовочный файл в языке программирования C и C++, который предоставляет доступ к некоторым системным вызовам (system calls) в операционных системах Unix-подобных, таких как Linux.

Этот заголовочный файл содержит объявления функций, константы и определения, которые позволяют программам взаимодействовать с операционной системой. Например, в нем содержатся функции для работы с файлами, процессами, директориями, сетевыми соединениями и другими системными ресурсами.

Вот некоторые из наиболее часто используемых функций и символов <unistd.h>:

fork(): Создание нового процесса.
exec(): Замена текущего процесса новым процессом.
dup(): Дублирование файловых дескрипторов.
close(): Закрытие файловых дескрипторов.
read(): Чтение данных из файла или дескриптора.
write(): Запись данных в файл или дескриптор.
getpid(): Получение идентификатора текущего процесса.
getppid(): Получение идентификатора родительского процесса.

#для_продвинутых
Dependency Injection

Dependency Injection (DI) — это паттерн проектирования, который помогает управлять зависимостями в приложениях. Он особенно важен в объектно-ориентированных языках программирования, таких как C++, где классы и объекты играют центральную роль.

DI предполагает, что зависимости (например, объекты других классов, которые класс использует) должны передаваться в класс извне, а не создаваться им самостоятельно. Это делает класс более независимым и более тестируемым. В C++, DI можно реализовать следующими способами: внедрение через конструктор, внедрение через метод и использование фабрик. В картинке с примером мы используем внедрение через конструктор, так как это самый распространенный способ DI в C++. В конструкторе класса вы передаете зависимости как параметры.

Использование DI в C++ способствует лучшей организации кода, более простой поддержке и тестированию. Он позволяет избегать жестких зависимостей и делает ваш код более гибким и расширяемым.

#для_продвинутых
Spinlock

Spinlock — это механизм синхронизации, который используется для управления доступом к общим ресурсам в многопоточных приложениях. Он представляет собой примитив синхронизации, который блокирует выполнение потока, пока он не сможет получить доступ к ресурсу.

Spinlock работает следующим образом:

1. Поток, который хочет получить доступ к общему ресурсу, пытается захватить spinlock.
2. Если spinlock свободен, поток захватывает его и продолжает выполнение.
3. Если spinlock уже занят другим потоком, текущий поток не блокируется в ожидании ресурса, а активно «крутится» (spin) в цикле, проверяя, не освободился ли spinlock. Это называется «захватом на занятом ресурсе».
4. Как только spinlock становится доступным, поток захватывает его и продолжает выполнение.

#для_продвинутых
«Static initialization order fiasco»

«Static initialization order fiasco» (фиаско порядка статической инициализации) — это проблема, которая может возникнуть в C++ при инициализации статических переменных или объектов в разных переводимых единицах или при использовании статических переменных в разных библиотеках.

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

#для_продвинутых
std::unordered_map

std::unordered_map в C++ является частью стандартной библиотеки и представляет собой реализацию хеш-таблицы, которая позволяет хранить пары ключ-значение и обеспечивает быстрый доступ к значениям по ключу. Она является одним из контейнеров STL (Standard Template Library).

#для_продвинутых
Декларация

Декларация — это объявление имени сущности (переменной, функции, класса и т. д.) без определения ее типа или реализации. Декларации используются для предварительного объявления сущности в программе, чтобы компилятор знал о ее существовании, но не обязан знать ее полную информацию или реализацию на этом этапе. Это полезно, когда вы хотите использовать сущность в разных частях вашей программы.

Обратите внимание, что декларации часто используются в заголовочных файлах (.h или .hpp), чтобы предоставить интерфейс к функциям или классам, а затем реализация определяется в соответствующих исходных файлах (.cpp). Это помогает разделить интерфейс и реализацию и упростить структуру проекта.

#для_начинающих
В чем отличие malloc от new?

malloc — выделение блока памяти в стиле Си, опасное с точки зрения приведения типов (non-typesafe), т.к. возвращает void* и требует обязательного приведения.

new — выделение блока памяти и последующий вызов конструктора, безопасное с точки зрения приведения типов (typesafe), т.к. тип возвращаемого значения определен заранее.

#для_продвинутых
override

Ключевое слово override используется для указания того, что функция в производном классе представляет собой переопределение (override) функции базового класса. Это помогает убедиться, что функция в производном классе действительно переопределяет функцию базового класса, и при компиляции будет сгенерирована ошибка, если это не так.

#для_начинающих
Флажки компиляции

Флажки компиляции — это опции или параметры, которые передаются компилятору программного кода для управления процессом компиляции. Компиляторы - это программы, которые преобразуют исходный код программы, написанный на языке программирования, в машинный код или другой формат, который может быть выполнен компьютером.

Флажки компиляции используются для различных целей, таких как оптимизация кода, установка целевой архитектуры, включение или выключение определенных функций и возможностей языка программирования, а также для управления процессом отладки и создания исполняемых файлов.

#для_продвинутых
Stellarium — это бесплатное программное обеспечение GPL, которое визуализирует реалистичное небо в реальном времени с помощью OpenGL. Он доступен для Linux/Unix, Windows и macOS. В Stellarium вы действительно видите то, что можете увидеть своими глазами, биноклем или небольшим телескопом.

https://www.libhunt.com/r/stellarium
Redis plus plus

Redis – это быстрое хранилище данных типа «ключ‑значение» в памяти с открытым исходным кодом.

Redis plus plus - это клиентская библиотека C++ для работы с Redis.

git clone https://github.com/redis-developer/redis-plus-plus-modules.git
cd redis-plus-plus-modules
./bootstrap.sh
./configure
make -j8

🖥 Github
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое виртуальный деструктор и зачем он используется в C++?

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

Если виртуального деструктора не объявлено в базовом классе, то при удалении производного объекта через указатель на базовый класс будут вызываны только деструкторы базового класса, что может привести к утечкам памяти и неопределенному поведению.
Поиск в ширину

Поиск в ширину (breadth-first search, BFS) - это алгоритм поиска или обхода графа. Он исследует все вершины на одном уровне, прежде чем переходить к следующему уровню.

Этот пример иллюстрирует обход в ширину для следующего графа:
0
/ \
1-----2
\
3
Начиная с вершины 2, алгоритм BFS посетит вершины в следующем порядке: 2, 0, 3, 1.
Статья Bungie о том, как они программируют такие игры, как Destiny, с использованием C++, и о правилах, которые они для этого создали.

https://www.bungie.net/7/en/News/Article/50666
std::invoke

std::invoke — это шаблонная функция, добавленная в C++17, которая позволяет вызывать произвольные объекты, как функции. Она может быть полезна в различных ситуациях, таких как вызов функций-членов, вызов лямбда-выражений и вызов функций с неизвестным типом.

Синтаксис:
std::invoke(callable, args...);


callable: объект, который будет вызван как функция. Это может быть указатель на функцию, функтор, лямбда-выражение или любой другой объект, который имеет оператор вызова().
args: аргументы, которые будут переданы callable.

#для_продвинутых
std::placeholders

std::placeholders — это пространство имен в стандартной библиотеке C++, которое содержит набор объектов-заполнителей (_1, _2, ..., _N), используемых при работе с функцией std::bind.

Функция std::bind позволяет связывать аргументы с функцией, создавая новый объект-функцию, который может быть вызван позже. Заполнители в std::placeholders используются для обозначения мест в списке аргументов, где будут подставлены значения при вызове нового объекта-функции.

#для_продвинутых
Создаем свою STL-совместимую реализацию std::allocator с лучшей производительностью

Реализация защиты от сбоев из-за фрагментации кучи и повышение скорости выполнения с помощью STL-альтернативы std::allocator, работающей с блоками памяти фиксированного размера.

Смотреть статью
std::swap_ranges

Эта функция меняет местами элементы в двух диапазонах. Это может быть полезно для сортировки элементов или перемещения элементов между двумя контейнерами.

#для_начинающих