Senior C++ Developer
12.7K subscribers
1.31K photos
3 videos
598 links
Изучаем C++.

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

РКН: https://www.gosuslugi.ru/snet/676e9a1e4e740947beca35ba
Download Telegram
Функция memmove

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

Прототип функции memmove выглядит следующим образом:

void* memmove(void* destination, const void* source, size_t num);


Здесь:

destination — указатель на начало блока памяти, в который нужно переместить данные.
source — указатель на начало блока памяти, из которого нужно скопировать данные.
num — количество байтов, которые нужно переместить.

Функция memmove обеспечивает корректное копирование данных, даже если destination и source перекрываются. Это означает, что она может быть использована в случаях, когда memcpy может привести к неправильным результатам из-за перекрытия.

#для_продвинутых
Функция floor

Функция floor в C++ используется для округления числа с плавающей запятой (типа float или double) вниз до ближайшего целого числа, которое меньше или равно исходному числу. Функция floor является частью стандартной библиотеки C++ и объявлена в заголовочном файле <cmath>.

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

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

CUDA (Compute Unified Device Architecture) — это платформа для параллельных вычислений, разработанная NVIDIA, которая позволяет использовать графические процессоры (GPU) для ускорения вычислений. CUDA позволяет программистам писать код на C++ для выполнения на GPU. Вот основные шаги по использованию CUDA в C++:

1. Установите необходимое программное обеспечение.
— Установите драйверы CUDA для вашей видеокарты с официального сайта NVIDIA.
— Установите среду разработки, такую как NVIDIA CUDA Toolkit, которая включает в себя компилятор NVCC и другие инструменты для разработки на CUDA.

2. Напишите CUDA-ядро.
— Создайте функцию на C++, которая будет выполняться на GPU. Эта функция обычно называется «ядром».
— Пометьте функцию ключевым словом __global__, чтобы указать, что она будет выполняться на GPU.

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

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

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

#для_продвинутых
Барьеры памяти

Барьеры памяти (memory barriers) используются для управления порядком доступа к памяти в многозадачных и многопоточных программах. Барьеры памяти помогают гарантировать, что операции чтения и записи выполняются в правильной последовательности, чтобы избежать гонок данных и неопределенного поведения.

В C++ барьеры памяти можно устанавливать с использованием стандартных библиотечных средств, таких как атомарные операции и мьютексы, а также с использованием модификаторов памяти, таких как volatile и std::memory_order

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

try_emplace
— это одна из функций в стандартной библиотеке C++, введенная в стандарте C++17. Она используется для вставки элементов в контейнеры, такие как std::map, std::unordered_map, std::set, и std::unordered_set, с оптимизированным процессом вставки.

Сигнатура try_emplace выглядит следующим образом:

template<class... Args>
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);


Она принимает ключ k и набор аргументов Args, которые используются для создания значения, которое будет ассоциировано с этим ключом. Функция возвращает пару, где первый элемент — итератор к вставленному или уже существующему элементу, а второй элемент — флаг, указывающий, был ли элемент вставлен (true) или уже существовал (false).

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

#для_продвинутых
Различия между ссылками и указателями

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

Ссылки

- Ссылка - это псевдоним для уже существующей переменной и создается с момента определения.
- Нельзя создать ссылку без инициализации; она должна быть связана с объектом.
- После инициализации нельзя переназначить ссылку на другой объект.
- Ссылка не имеет собственного адреса в памяти - взятие адреса ссылки даст адрес объекта, который она представляет.
- Ссылка не может быть "пустой" и всегда ссылается на валидный объект.
- Ссылка разыменовывается автоматически при использовании, избегая необходимости явного разыменования.
- Ссылку нельзя переопределить, она всегда ссылается на один и тот же объект после инициализации.

Указатели

- Указатель - это переменная, которая хранит адрес объекта в памяти.
- Указатель может быть инициализирован, но может быть и просто объявлен, в отличие от ссылки, и, следовательно, может быть "пустым" (например, иметь значение nullptr).
- Указатель необходимо явно разыменовывать для доступа к значению объекта, на который он указывает.
- Указатели могут использоваться для создания множественных уровней индирекции (например, указатель на указатель).
- Можно объявлять массивы указателей, в отличие от ссылок.
- Указатели поддерживают арифметику указателей: их можно инкрементировать и декрементировать, что полезно при работе с массивами и итерировании.
- В случае указателей можно применять сравнения, в том числе с проверкой на nullptr, чтобы определить, указывает ли указатель на объект.

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

Критическая секция — это участок кода, который должен быть выполнен только одним потоком в определенный момент времени, чтобы избежать гонок данных (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