Senior C++ Developer – Telegram
Senior C++ Developer
12.3K subscribers
1.36K photos
3 videos
609 links
Изучаем C++.

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

РКН: https://www.gosuslugi.ru/snet/676e9a1e4e740947beca35ba
Download Telegram
#вопросы_с_собеседований
Какие накладные расходы связаны с вызовом виртуальной функции?

При вызове виртуальной функции происходят следующие накладные расходы:

1. Поиск в таблице виртуальных функций (vtable):
для вызова виртуальной функции компилятор должен сначала получить указатель на нужную функцию из vtable класса. Это занимает некоторое время.

2. Невозможность инлайнинга:
тело виртуальной функции неизвестно на этапе компиляции, поэтому оптимизация инлайнинга для таких функций невозможна.

4. Затраты памяти на vtable:
для каждого класса с виртуальными функциями нужно хранить таблицу vtable, что увеличивает расход памяти.
std::sort

std::sort - это функция стандартной библиотеки для сортировки элементов в контейнерах, таких как вектор или список.
Чтобы использовать std::sort, нужно подключить заголовочный файл <algorithm>.

Метод принимает в качестве аргументов итераторы на начало и конец сортируемой последовательности и сортирует элементы в возрастающем порядке по умолчанию.

Для определения порядка сортировки можно указать свой компаратор.

#это_база
#вопросы_с_собеседований
В чем разница между статической и динамической библиотеками?

- Статические библиотеки компонуются с программой на этапе компиляции, а динамические подключаются во время выполнения программы.

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

- Статические библиотеки увеличивают размер конечного файла программы, динамические - нет.

- Если статическая библиотека обновляется, нужно перекомпилировать программу. Для динамической библиотеки достаточно заменить файл библиотеки.

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

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

Несмотря на разделение кода по файлам, при компиляции программы компоновщик свяжет объявление и реализацию вместе и позволит вызвать print() в main().
reference_wrapper

reference_wrapper - это класс-обёртка для ссылок из заголовочного файла <functional>. Он позволяет передавать ссылки как значения.

Основное преимущество в том, что reference_wrapper ведёт себя как ссылка, но может копироваться как значение. Это избавляет от необходимости использовать указатели в подобных сценариях.

В этом примере мы передаем ссылку на переменную value в функцию process, используя std::ref для создания объекта std::reference_wrapper.
В функции process мы можем работать со ссылкой, как если бы она была передана напрямую, используя метод get() для получения самой ссылки.
Ключевое слово const

Ключевое слово const используется для создания констант и неизменяемых объектов.

- Const для объявления переменных: запрещает изменение объекта после инициализации.

- Const указатели и ссылки: указатель или ссылка на константный объект. Нельзя изменить объект через них, только читать.

- Функции, возвращающие const значения: гарантируют, что функция не изменит объект.

- Const члены класса: нельзя изменить через объект класса.

- Const методы класса: не меняют члены класса. Часто применяются к getter-методам.

#это_база
#вопросы_с_собеседований
Что такое рефакторинг?

Рефакторинг - это процесс изменения внутренней структуры программы без изменения ее внешнего поведения.

Рефакторинг кода может применяться в следующих ситуациях:

- Улучшение читаемости и понятности кода.
- Оптимизация производительности.
- Устранение дублирования кода.

Рефакторинг особенно важен при работе над большими проектами, где код многократно изменяется и расширяется. Он позволяет поддерживать кодбейз чистым, современным и масштабируемым.
std::tuple

std::tuple - это шаблонный класс, представляющий собой фиксированный набор элементов разных типов. Проще говоря, удобный инструмент для упаковки данных разных типов

Элементы tuple инициализируются в конструкторе и доступны только для чтения после создания.

tuple часто используется в комбинации с tie для присваивания кортежа переменным.

#это_база
#вопросы_с_собеседований
Что такое union?

Union - это специальный класс, который позволяет хранить данные разных типов в одной области памяти.
Основные характеристики:

- Объявляется с ключевым словом union.
- В каждый момент активно только одно поле.
- Размер равен наибольшему полю.
- Позволяет интерпретировать одну область памяти разными способами.
- Экономит память.
- Доступ к полям как в обычном классе.
msg_ptr (message pointer)

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

Использование указателей вместо копирования данных позволяет избежать лишних копий и ускорить передачу сообщений между потоками.

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

Метод before_begin() контейнера forward_list возвращает итератор, указывающий на позицию перед первым элементом списка.

Это полезно, например, чтобы вставить элемент в начало списка.

Работает за константное время O(1), т.к. получает ссылку на начало списка.

#это_база
try_emplace

Метод try_emplace() в C++17 - это один из способов вставки элемента в ассоциативный контейнер (например, map или unordered_map).

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

Преимущества:
- Более эффективно, чем insert, т.к. сразу конструирует элемент на месте.
- Не делает лишних копирований или перемещений.
- Позволяет избежать ненужного перезаписывания элемента по существующему ключу.
#вопросы_с_собеседований
Почему std::make_pair больше не нужна?

В новых стандартах C++ она утратила актуальность по нескольким причинам:

— Появились инициализаторы со скобками {} для создания std::pair напрямую.
— Для вставки в контейнеры теперь есть функция emplace(), которая конструирует элемент прямо на месте.
— Можно использовать агрегатную инициализацию.
— Инициализаторы из C++17 позволяют сразу указывать ключ и значение.
insert_or_assign

insert_or_assign
это функция из стандартной библиотеки языка C++, добавленная в C++17. Она используется для вставки элемента в ассоциативный контейнер (например, std::map) или обновления значения элемента, если ключ уже существует.

Преимущества перед operator[]:

— Более безопасна, так как проверяет существование элемента.
— Избавляет от лишнего кода для проверки наличия ключа.
std::size

std::size
это функция из стандартной библиотеки C++, которая возвращает размер контейнера или массива.

Она определена в заголовочном файле <iterator>, работает со всеми стандартными контейнерами (vector, deque, list, array и др.) и с массивами всех типов, позволяя получить размер контейнера или массива в runtime.

#это_база
Атрибут nodiscard

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

Он был добавлен в С++17 для улучшения качества кода, указывается перед объявлением функции или метода и информирует компилятор, что возвращаемое значение не должно игнорироваться.
Позволяет избежать логических ошибок при игнорировании важных результатов функции.

В этом примере функция getResult() помечена атрибутом [[nodiscard]].
При вызове getResult() без использования возвращаемого значения компилятор выдаст предупреждение об игнорировании результата.
Функция strrchr()

Функция strrchr(), объявленная в заголовочном файле <cstring>, ищет последнее вхождение указанного символа в строке и возвращает указатель на это вхождение.

Принимает два параметра: указатель на строку и символ для поиска, возвращает указатель на последнее вхождение символа в строке. Если символ не найден, возвращается нулевой указатель.

Полезна, когда нужно найти последнее вхождение разделителя, например точки в URL.

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

#это_база
#вопросы_с_собеседований
Что такое сложность алгоритма и от чего она зависит?

Сложность алгоритма - это количественная характеристика его эффективности, которая показывает, как зависят затраты ресурсов (времени, памяти) от размера входных данных.

Сложность зависит от:

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

Чем быстрее растёт сложность функции с ростом входных данных, тем менее эффективен алгоритм.
absl::btree

absl::btree
— это реализация B-дерева в библиотеке Abseil для C++.
Преимущества absl::btree — это хранение данных в отсортированном порядке, быстрый поиск, вставка и удаление за O(logN), поддержка уникальных и неуникальных ключей, реализация set и map.

Применяется в задачах, где нужна высокопроизводительная структура данных с отсортированным доступом, например:

Реализация словарей и сортированных множеств;
Для хранения данных в базах данных;
В поисковых системах для индексов;
В структурах вроде кэша для быстрого доступа;
В задачах машинного обучения для хранения данных.
std::clamp

std::clamp
это функция из стандартной библиотеки, которая позволяет ограничить значение в заданном диапазоне.

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

Применяется для:

— Ограничения числовых значений в заданных пределах.
— Обработки данных из недостоверных источников.
— Защиты от переполнения/обрезания данных.
— Нормализации данных в ML и компьютерном зрении.
— Реализации игровой логики в движках.
— Обработки аудио- и видео- сигналов.
Алгоритм generate

std::generate
— это алгоритм из стандартной библиотеки C++, который используется для заполнения диапазона элементов сгенерированными значениями.

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

В этом примере std::generate совместно с генератором случайных чисел используется для быстрого заполнения вектора случайными значениями.

#это_база