assert()
assert() - макроопределение для вывода отладочных диагностических сообщений. Используется для включения в программу диагностических операторов и принимает один аргумент (int expression).
Аpгyмент expression должен быть выражением, которое принимает значение истина (не ноль), если программа работает так, как вы предполагаете.
Когда expression ложно (ноль), assert вызывает abort, предварительно выведя сообщение, показывающие, какая и где произошла ошибка:
assertion failed: expression, file filename, line lineno
assert() - макроопределение для вывода отладочных диагностических сообщений. Используется для включения в программу диагностических операторов и принимает один аргумент (int expression).
Аpгyмент expression должен быть выражением, которое принимает значение истина (не ноль), если программа работает так, как вы предполагаете.
Когда expression ложно (ноль), assert вызывает abort, предварительно выведя сообщение, показывающие, какая и где произошла ошибка:
assertion failed: expression, file filename, line lineno
#вопросы_с_собеседований
Напишите алгоритм обхода графа в глубину.
Результатом должен стать код, который представляет из себя алгоритм обхода графа в глубину (DFS - Depth First Search). Пример представлен на изображении.
Напишите алгоритм обхода графа в глубину.
Результатом должен стать код, который представляет из себя алгоритм обхода графа в глубину (DFS - Depth First Search). Пример представлен на изображении.
Почему код выше выводит числа, а не символы?
Anonymous Quiz
21%
Нет перегрузки basic_ostream принимающей тип chat.
25%
Код ведет себя верно, ведь в массив записаны числа типа int.
54%
Поведение определено перегрузкой operator<< принимающего char.
Применение указателя unique_ptr<T>
В функции foo1 мы выделяем память для указателя ptr и затем освобождаем ее с помощью оператора delete. Однако, если произойдет исключение во время работы функции, то память не будет освобождена, что приведет к утечке памяти.
Во втором примере мы используем
Таким образом, мы можем гарантировать, что ресурсы будут корректно освобождены, даже в случае исключения.
Данный тип указателей полезен, когда нужен указатель на объект, на который НЕ будет других указателей и который будет удален после удаления указателя.
В функции foo1 мы выделяем память для указателя ptr и затем освобождаем ее с помощью оператора delete. Однако, если произойдет исключение во время работы функции, то память не будет освобождена, что приведет к утечке памяти.
Во втором примере мы используем
std::unique_ptr, который выделяет память при инициализации и освобождает память при уничтожении объекта.Таким образом, мы можем гарантировать, что ресурсы будут корректно освобождены, даже в случае исключения.
Данный тип указателей полезен, когда нужен указатель на объект, на который НЕ будет других указателей и который будет удален после удаления указателя.
Механизм синхронизации mutex
Мьютекс блокирует доступ к ресурсу, пока поток не освободит его. Мьютекс может быть заблокирован только одним потоком в определенный момент времени. При попытке другого потока заблокировать мьютекс, он будет заблокирован до тех пор, пока первый поток не разблокирует его.
Синтаксис:
Заголовочный файл |
Мьютекс блокирует доступ к ресурсу, пока поток не освободит его. Мьютекс может быть заблокирован только одним потоком в определенный момент времени. При попытке другого потока заблокировать мьютекс, он будет заблокирован до тех пор, пока первый поток не разблокирует его.
Синтаксис:
Заголовочный файл |
#include <mutex>
Объявление | std::mutex mutex_name;
Захват мьютекса | mutex_name.lock();
Освобождение мьютекса | mutex_name.unlock();#вопросы_с_собеседований
Что такое хеш-функция? Объясните на примере
Хеш-функция - это функция, которая принимает на вход некоторые данные и возвращает фиксированный размер выходных данных, называемый хешем. Такие функции широко используются в C++ для решения задач с поиском и индексированием данных. Они позволяют быстро находить элементы в массивах или хранилищах данных.
Рассмотрим применение на примере кода выше:
Мы создаем объект хеш-функции для строки и используем его для вычисления хеша для строки "Hello, world!". Результатом выполнения программы будет вывод на экран хеш-значения для этой строки.
Что такое хеш-функция? Объясните на примере
Хеш-функция - это функция, которая принимает на вход некоторые данные и возвращает фиксированный размер выходных данных, называемый хешем. Такие функции широко используются в C++ для решения задач с поиском и индексированием данных. Они позволяют быстро находить элементы в массивах или хранилищах данных.
Рассмотрим применение на примере кода выше:
Мы создаем объект хеш-функции для строки и используем его для вычисления хеша для строки "Hello, world!". Результатом выполнения программы будет вывод на экран хеш-значения для этой строки.
Что произойдет в результате работы этой программы?
Anonymous Quiz
26%
Ошибки компиляции
37%
Вывод переменной а
37%
Исключение вызовет Debug error
Кортежи
Как и пара, кортеж представляет собой набор значений фиксированного размера для различных типов данных.
Иногда удобнее использовать
Как и пара, кортеж представляет собой набор значений фиксированного размера для различных типов данных.
Иногда удобнее использовать
std::array вместо кортежа. Такой массив подобен обычному массиву в Си вместе с несколькими функциями стандартной библиотеки C++. Эта структура данных была добавлена в 11 версии C++.SFINAE (Substitution Failure Is Not An Error)
Это механизм в C++, который позволяет компилятору выбирать наиболее специфичный шаблон функции или класса, когда для нескольких шаблонов применимы одинаковые параметры, но с разными типами.
В этом примере функция
Это механизм в C++, который позволяет компилятору выбирать наиболее специфичный шаблон функции или класса, когда для нескольких шаблонов применимы одинаковые параметры, но с разными типами.
В этом примере функция
my_function будет компилироваться только для типов данных, которые являются целочисленными. Если мы передадим в функцию строку, то компиляция завершится неудачей, потому что std::enable_if_t не сможет замениться на допустимый тип.Есть ли преимущества одного фрагмента кода перед другим? Если да, то какие?
Хотя оба варианта выполняют одно и то же, второй вариант лучше с точки зрения производительности. Это связано с тем, что оператор постинкремента itr++ дороже, чем оператор предварительного инкремента ++itr. Базовая реализация оператора постинкремента создает копию элемента перед его увеличением, а затем возвращает копию.
Тем не менее, многие компиляторы автоматически оптимизируют первый вариант, преобразовывая его во второй.
Тем не менее, многие компиляторы автоматически оптимизируют первый вариант, преобразовывая его во второй.
#вопросы_с_собеседований
Возможно ли иметь рекурсивную встроенную функцию?
Хотя вы можете вызывать встроенную функцию из самой себя, компилятор может не генерировать встроенный код, поскольку не может определить глубину рекурсии во время компиляции.
Компилятор с хорошим оптимизатором может встраивать рекурсивные вызовы до некоторой глубины, зафиксированной во время компиляции (скажем, три или пять рекурсивных вызовов), и вставлять нерекурсивные вызовы во время компиляции для случаев, когда фактическая глубина будет превышена во время выполнения.
Возможно ли иметь рекурсивную встроенную функцию?
Компилятор с хорошим оптимизатором может встраивать рекурсивные вызовы до некоторой глубины, зафиксированной во время компиляции (скажем, три или пять рекурсивных вызовов), и вставлять нерекурсивные вызовы во время компиляции для случаев, когда фактическая глубина будет превышена во время выполнения.
Метод exchange()
Этот метод позволяет заменить значение переменной на новое значение и вернуть старое значение.
В данном примере значение переменной
Cледует заметить, что данная функция является безопасной для многопоточной обработки, т.к. она гарантирует атомарность выполнения замены значения переменной.
Хотя этот метод не является очень распространенным, он часто используется для обмена значениями двух переменных, что может пригодиться для реализации алгоритмов, таких как quicksort, где нужно обменивать элементы массива.
Этот метод позволяет заменить значение переменной на новое значение и вернуть старое значение.
В данном примере значение переменной
a было заменено на 10, а старое значение (5) было сохранено в переменной b, которую вернул метод std::exchange().Cледует заметить, что данная функция является безопасной для многопоточной обработки, т.к. она гарантирует атомарность выполнения замены значения переменной.
Хотя этот метод не является очень распространенным, он часто используется для обмена значениями двух переменных, что может пригодиться для реализации алгоритмов, таких как quicksort, где нужно обменивать элементы массива.
ACID (Atomicity, Consistency, Isolation, Durability)
В языке C++ концепция ACID может использоваться при работе с базами данных, например, при использовании библиотеки SQLite. ACID гарантирует, что транзакции будут выполнены одновременно и когда они закончатся, база данных находится в согласованном состоянии.
Atomicity гарантирует, что транзакция будет выполнена как одно целое и либо полностью, либо не выполнится вообще.
Consistency гарантирует, что данные в базе будут согласованы с правилами и ограничениями базы данных.
Isolation гарантирует, что транзакции будут выполнены независимо друг от друга и не будут влиять друг на друга.
Durability гарантирует, что данные в базе данных сохранятся даже в случае сбоев или отказа оборудования.
В языке C++ концепция ACID может использоваться при работе с базами данных, например, при использовании библиотеки SQLite. ACID гарантирует, что транзакции будут выполнены одновременно и когда они закончатся, база данных находится в согласованном состоянии.
Atomicity гарантирует, что транзакция будет выполнена как одно целое и либо полностью, либо не выполнится вообще.
Consistency гарантирует, что данные в базе будут согласованы с правилами и ограничениями базы данных.
Isolation гарантирует, что транзакции будут выполнены независимо друг от друга и не будут влиять друг на друга.
Durability гарантирует, что данные в базе данных сохранятся даже в случае сбоев или отказа оборудования.
#вопросы_с_собеседований
Что выводит код выше?
Вывод будет выглядеть так:
from A
from A
from Base
Здесь важно отметить порядок уничтожения классов и то, как Base метод возвращается к своей собственной реализации после уничтожения.
Что выводит код выше?
from A
from A
from Base
Здесь важно отметить порядок уничтожения классов и то, как Base метод возвращается к своей собственной реализации после уничтожения.
#вопросы_с_собеседований
В чем проблема с этим кодом?
Поведение не определено, потому что деструктор не является виртуальным.
Из спецификации:
( C++11 §5.3.5/3 ) - если статический тип удаляемого объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа удаляемого объекта, а статический тип должен иметь виртуальный деструктор, иначе поведение не определено.
В чем проблема с этим кодом?
Из спецификации:
( C++11 §5.3.5/3 ) - если статический тип удаляемого объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа удаляемого объекта, а статический тип должен иметь виртуальный деструктор, иначе поведение не определено.
Обфускация
Обфускация - это процесс преобразования исходного кода программы в нечитаемый для человека вид, но сохраняющий работоспособность программы.
Чаще всего применяется для защиты кода от несанкционированного использования, взломов и раскрытия алгоритмов работы программы. Это может быть особенно важным для программ, которые содержат ценную информацию или используются в критических системах.
Такой код использует множество макросов, которые заменяют имена переменных и функций на случайные символы. Также, для усложнения чтения кода, используется множество пустых строк и лишних пробелов.
* На изображении слева представлен обычный код, а справа - его версия после обфускации
Обфускация - это процесс преобразования исходного кода программы в нечитаемый для человека вид, но сохраняющий работоспособность программы.
Чаще всего применяется для защиты кода от несанкционированного использования, взломов и раскрытия алгоритмов работы программы. Это может быть особенно важным для программ, которые содержат ценную информацию или используются в критических системах.
Такой код использует множество макросов, которые заменяют имена переменных и функций на случайные символы. Также, для усложнения чтения кода, используется множество пустых строк и лишних пробелов.
* На изображении слева представлен обычный код, а справа - его версия после обфускации
Расширение CUDA
CUDA extension позволяет использовать функции NVIDIA CUDA в C++ коде. Оно предоставляет библиотеку из заголовочных файлов и библиотеку объектных файлов для компиляции. Преимущества использования расширения CUDA:
В данном примере мы объявляем ядро (kernel)
CUDA extension позволяет использовать функции NVIDIA CUDA в C++ коде. Оно предоставляет библиотеку из заголовочных файлов и библиотеку объектных файлов для компиляции. Преимущества использования расширения CUDA:
- возможность использования мощностей графического процессора (GPU) для ускорения вычислений;- удобный синтаксис и возможность использования функций CUDA в C++ коде;- поддержка различных операционных систем (Windows, Linux, macOS).В данном примере мы объявляем ядро (kernel)
add, которое складывает два числа и записывает результат в указатель c. Затем мы выделяем память на устройстве (GPU) для переменной dev_c, вызываем ядро add, копируем результат в переменную c на хосте (CPU) и освобождаем память, выделенную на устройстве.#вопросы_с_собеседований
Сколько раз будет выполняться этот цикл? Поясните свой ответ.
Если бы вы сказали 300, вы были бы правы, если бы i было объявлено как int. Однако, поскольку i было объявлено как unsigned char, правильным ответом будет то, что этот код приведет к бесконечному циклу.
Вот почему:
Выражение 2 * half_limit будет преобразовано в int (по правилам преобразования C++) и будет иметь значение 300. Однако, поскольку i - это беззнаковый символ, он будет пересчитан в 8-битное значение, которое, достигнув 255, переполнится (то есть вернется к 0), и цикл, таким образом, будет продолжаться вечно.
Сколько раз будет выполняться этот цикл? Поясните свой ответ.
Вот почему:
Выражение 2 * half_limit будет преобразовано в int (по правилам преобразования C++) и будет иметь значение 300. Однако, поскольку i - это беззнаковый символ, он будет пересчитан в 8-битное значение, которое, достигнув 255, переполнится (то есть вернется к 0), и цикл, таким образом, будет продолжаться вечно.