Что такое класс хранения?
Класс, который определяет срок существования, компоновку и расположение переменных/функций в памяти.
В C++ поддерживаются такие классы хранения: auto, static, register, extern и mutable.
Обратите внимание, что register устарел для C++11. Для C++17 он был удален и зарезервирован для будущего использования.
Класс, который определяет срок существования, компоновку и расположение переменных/функций в памяти.
В C++ поддерживаются такие классы хранения: auto, static, register, extern и mutable.
Обратите внимание, что register устарел для C++11. Для C++17 он был удален и зарезервирован для будущего использования.
Объясните ключевые слова mutable и volatile.
Ключевое слово volatile сообщает компилятору, что переменная может измениться без ведома компилятора. Переменные, объявленные как volatile, не будут кэшироваться компилятором и, таким образом, всегда будут считываться из памяти.
Ключевое слово mutable можно использовать для переменных-членов класса. Изменяемые переменные могут меняться из константных функций-членов класса.
Ключевое слово volatile сообщает компилятору, что переменная может измениться без ведома компилятора. Переменные, объявленные как volatile, не будут кэшироваться компилятором и, таким образом, всегда будут считываться из памяти.
Ключевое слово mutable можно использовать для переменных-членов класса. Изменяемые переменные могут меняться из константных функций-членов класса.
Для чего используется ключевое слово explicit?
Ключевое слово explicit используется для того, чтобы пометить конструкторы, которые не должны неявно преобразовывать типы. Оно является необязательным для конструкторов, которые принимают ровно один аргумент, и работает на конструкторах (с одним аргументом), так как только эти конструкторы могут использоваться при приведении типов.
Ключевое слово explicit используется для того, чтобы пометить конструкторы, которые не должны неявно преобразовывать типы. Оно является необязательным для конструкторов, которые принимают ровно один аргумент, и работает на конструкторах (с одним аргументом), так как только эти конструкторы могут использоваться при приведении типов.
Перечислите все способы синхронизации процессов.
1. Использование мьютексов (std::mutex). Мьютекс позволяет захватывать его одним потоком, блокируя доступ другим потокам.
2. Использование семафоров (std::semaphore). Семафоры позволяют ограничивать количество потоков, которые могут одновременно захватить семафор.
3. Использование условных переменных (std::condition_variable). Они позволяют блокировать поток до наступления некоторого события.
4. Использование флагов и барьеров (std::atomic_flag, std::barrier).
5. Передача сообщений между потоками через очереди (std::queue).
6. Использование фьючерсов и промисов (std::promise, std::future).
Выбор конкретного механизма зависит от сценария использования и требований к синхронизации. Главное при этом избегать длительных и взаимных блокировок.
1. Использование мьютексов (std::mutex). Мьютекс позволяет захватывать его одним потоком, блокируя доступ другим потокам.
2. Использование семафоров (std::semaphore). Семафоры позволяют ограничивать количество потоков, которые могут одновременно захватить семафор.
3. Использование условных переменных (std::condition_variable). Они позволяют блокировать поток до наступления некоторого события.
4. Использование флагов и барьеров (std::atomic_flag, std::barrier).
5. Передача сообщений между потоками через очереди (std::queue).
6. Использование фьючерсов и промисов (std::promise, std::future).
Выбор конкретного механизма зависит от сценария использования и требований к синхронизации. Главное при этом избегать длительных и взаимных блокировок.
Какой код выполняется до функции main?
Ответ:
Конструкторы глобальных объектов.
Ответ:
Что такое cache miss и как это выявить?
Cache miss — это событие, когда система или приложение делает запрос на получение данных из кэша, но эти данные в данный момент отсутствуют в кэш-памяти. В результате системе или приложению приходится делать вторую попытку найти данные, на этот раз в более медленной основной базе данных.
Чтобы выявить cache miss в C++, вы можете использовать инструменты профилирования, которые могут анализировать события, связанные с кэшем. Некоторые из таких инструментов включают:
Cachegrind: инструмент для профилирования кэша, который является частью набора инструментов Valgrind. Cachegrind может анализировать поведение кэша вашего приложения и предоставлять информацию о cache miss и других событиях, связанных с кэшем.
Perf: инструмент для профилирования производительности в Linux, который может использовать аппаратные счетчики процессора для анализа событий, связанных с кэшем.
OProfile: еще один инструмент для профилирования производительности в Linux, который также может использовать аппаратные счетчики процессора для анализа событий, связанных с кэшем.
Cache miss — это событие, когда система или приложение делает запрос на получение данных из кэша, но эти данные в данный момент отсутствуют в кэш-памяти. В результате системе или приложению приходится делать вторую попытку найти данные, на этот раз в более медленной основной базе данных.
Чтобы выявить cache miss в C++, вы можете использовать инструменты профилирования, которые могут анализировать события, связанные с кэшем. Некоторые из таких инструментов включают:
Cachegrind: инструмент для профилирования кэша, который является частью набора инструментов Valgrind. Cachegrind может анализировать поведение кэша вашего приложения и предоставлять информацию о cache miss и других событиях, связанных с кэшем.
Perf: инструмент для профилирования производительности в Linux, который может использовать аппаратные счетчики процессора для анализа событий, связанных с кэшем.
OProfile: еще один инструмент для профилирования производительности в Linux, который также может использовать аппаратные счетчики процессора для анализа событий, связанных с кэшем.
Могут ли статичные функции быть виртуальными в С++?
В C++ статическая функция-член класса не может быть виртуальной. Виртуальные функции вызываются, когда у вас есть указатель или ссылка на экземпляр класса. Статические функции не привязаны к экземпляру класса, но они привязаны к самому классу. C++ не имеет указателей на класс, поэтому нет сценария, в котором вы могли бы виртуально вызвать статическую функцию.
Например, программа с картинки в примере 1 выдаст ошибку во время компиляции.
Кроме того, статическая функция-член класса не может иметь одновременно идентификаторы const и volatile. Код из примера 2 тоже не скомпилируется.
В C++ статическая функция-член класса не может быть виртуальной. Виртуальные функции вызываются, когда у вас есть указатель или ссылка на экземпляр класса. Статические функции не привязаны к экземпляру класса, но они привязаны к самому классу. C++ не имеет указателей на класс, поэтому нет сценария, в котором вы могли бы виртуально вызвать статическую функцию.
Например, программа с картинки в примере 1 выдаст ошибку во время компиляции.
Кроме того, статическая функция-член класса не может иметь одновременно идентификаторы const и volatile. Код из примера 2 тоже не скомпилируется.
Что такое критическая секция?
Критическая секция — это участок кода, в котором происходит доступ к общему ресурсу (например, переменной или структуре данных), и который должен быть выполнен атомарно, то есть без возможности прерывания другими потоками.
Для обеспечения безопасного доступа к критической секции в C++ используются механизмы синхронизации, такие как мьютексы (std::mutex) и блокировки (std::lock_guard, std::unique_lock). Перед выполнением критической секции поток должен захватить мьютекс, блокируя его для других потоков. После завершения работы в критической секции мьютекс освобождается, позволяя другим потокам получить доступ к ресурсу.
Использование критических секций и мьютексов позволяет избежать состояний гонки (race conditions) и обеспечить корректную и безопасную работу с общими данными в многопоточных приложениях.
Критическая секция — это участок кода, в котором происходит доступ к общему ресурсу (например, переменной или структуре данных), и который должен быть выполнен атомарно, то есть без возможности прерывания другими потоками.
Для обеспечения безопасного доступа к критической секции в C++ используются механизмы синхронизации, такие как мьютексы (std::mutex) и блокировки (std::lock_guard, std::unique_lock). Перед выполнением критической секции поток должен захватить мьютекс, блокируя его для других потоков. После завершения работы в критической секции мьютекс освобождается, позволяя другим потокам получить доступ к ресурсу.
Использование критических секций и мьютексов позволяет избежать состояний гонки (race conditions) и обеспечить корректную и безопасную работу с общими данными в многопоточных приложениях.
Какие преимущества композиции перед наследованием?
Композиция в C++ позволяет создавать новый класс из более мелких существующих классов, тогда как наследование от других классов позволяет использовать существующие свойства класса.
Основное преимущество композиции заключается в том, что она обеспечивает более гибкую архитектуру и более легкое изменение поведения класса в будущем.
В то время как если использовать наследование при проектировании классов, то это может ограничить возможности изменений в будущем и привести к большему количеству ошибок в программе.
Композиция в C++ позволяет создавать новый класс из более мелких существующих классов, тогда как наследование от других классов позволяет использовать существующие свойства класса.
Основное преимущество композиции заключается в том, что она обеспечивает более гибкую архитектуру и более легкое изменение поведения класса в будущем.
В то время как если использовать наследование при проектировании классов, то это может ограничить возможности изменений в будущем и привести к большему количеству ошибок в программе.
Почему вызов container.size() перед каждой итерацией цикла является плохой практикой?
Вызов container.size() перед каждой итерацией по контейнеру не является оптимальным, так как это приводит к линейной сложности O(n).
Вместо этого лучше сохранить размер контейнера в переменную до цикла, таким образом размер вычисляется только один раз, а доступ к элементам в цикле происходит за константное время O(1).
Это позволяет избежать лишних вычислений размера на каждой итерации и улучшает производительность.
Вызов container.size() перед каждой итерацией по контейнеру не является оптимальным, так как это приводит к линейной сложности O(n).
Вместо этого лучше сохранить размер контейнера в переменную до цикла, таким образом размер вычисляется только один раз, а доступ к элементам в цикле происходит за константное время O(1).
Это позволяет избежать лишних вычислений размера на каждой итерации и улучшает производительность.
Мьютекс и Семафор: какой из них вы бы использовали для защиты доступа к операции приращения и почему?
Мьютекс и семафор — это два разных механизма синхронизации. Мьютекс используется для обеспечения взаимного исключения доступа к общим ресурсам, в то время как семафор используется для управления доступом к ограниченному числу ресурсов.
В случае операции приращения, которая должна быть выполнена атомарно, стоит использовать мьютекс. Он гарантирует, что только один поток может получить доступ к общему ресурсу в определенный момент времени. Это предотвращает состояние гонки и обеспечивает корректность работы программы.
Мьютекс и семафор — это два разных механизма синхронизации. Мьютекс используется для обеспечения взаимного исключения доступа к общим ресурсам, в то время как семафор используется для управления доступом к ограниченному числу ресурсов.
В случае операции приращения, которая должна быть выполнена атомарно, стоит использовать мьютекс. Он гарантирует, что только один поток может получить доступ к общему ресурсу в определенный момент времени. Это предотвращает состояние гонки и обеспечивает корректность работы программы.
Начать курс «Алгоритмы и структуры данных» с вводной части можно уже сегодня бесплатно
Курс для разработчиков, которые хотят подготовиться к собеседованию в технологическую компанию или продвинуться по карьерной лестнице.
НАЧАТЬ С ДЕМО-ДОСТУПА
▪️ бессрочный доступ
▪️ 47 видеолекций
▪️ 150 практических заданий
▪️ бессрочная поддержка в чате студентов
▪️развернутая обратная связь по всем домашним заданиям
🔹Подробная программа – https://proglib.io/w/b26c360b
Переходите, оставляйте заявку на пробную версию и знакомьтесь с самым харизматичным спикером – Степаном Мацкевичем. Он определенно получил приз зрительских симпатий от наших студентов🥰
Курс для разработчиков, которые хотят подготовиться к собеседованию в технологическую компанию или продвинуться по карьерной лестнице.
НАЧАТЬ С ДЕМО-ДОСТУПА
▪️ бессрочный доступ
▪️ 47 видеолекций
▪️ 150 практических заданий
▪️ бессрочная поддержка в чате студентов
▪️развернутая обратная связь по всем домашним заданиям
🔹Подробная программа – https://proglib.io/w/b26c360b
Переходите, оставляйте заявку на пробную версию и знакомьтесь с самым харизматичным спикером – Степаном Мацкевичем. Он определенно получил приз зрительских симпатий от наших студентов🥰
Почему стоит использовать std::swap вместо прямого обмена значений?
Использование std::swap вместо прямого обмена значений может быть более эффективным, так как std::swap может быть специализирован для определенных типов данных.
Это означает, что для некоторых типов данных может существовать более эффективная реализация std::swap, которая будет использоваться вместо общей реализации.
Также использование std::swap улучшает читаемость кода и делает его более ясным для других разработчиков.
Использование std::swap вместо прямого обмена значений может быть более эффективным, так как std::swap может быть специализирован для определенных типов данных.
Это означает, что для некоторых типов данных может существовать более эффективная реализация std::swap, которая будет использоваться вместо общей реализации.
Также использование std::swap улучшает читаемость кода и делает его более ясным для других разработчиков.
Расскажите об использовании realloc в контейнерах.
realloc используется в контейнерах динамической памяти, таких как vector, для изменения выделенной памяти при добавлении или удалении элементов.
realloc вызывается при заполнении текущего буфера в контейнере и память перевыделяется большими блоками (обычно в 2 раза больше). Это позволяет избежать постоянного выделения памяти заново.
Само перевыделение происходит автоматически, скрыто от разработчика.
При частых вызовах может привести к фрагментации памяти.
realloc используется в контейнерах динамической памяти, таких как vector, для изменения выделенной памяти при добавлении или удалении элементов.
realloc вызывается при заполнении текущего буфера в контейнере и память перевыделяется большими блоками (обычно в 2 раза больше). Это позволяет избежать постоянного выделения памяти заново.
Само перевыделение происходит автоматически, скрыто от разработчика.
При частых вызовах может привести к фрагментации памяти.
Что такое модульные тесты?
Модульные тесты (или юнит-тесты) — это специальные тестовые программы, которые разработчики создают для проверки отдельных модулей или компонентов своего кода на правильность работы. Модуль в данном контексте представляет собой небольшую, независимую часть программы, которую можно протестировать изолированно от других частей приложения.
Целью модульных тестов является убеждение в том, что каждый компонент работает как задумано и не вызывает ошибок или нежелательного поведения.
Модульные тесты (или юнит-тесты) — это специальные тестовые программы, которые разработчики создают для проверки отдельных модулей или компонентов своего кода на правильность работы. Модуль в данном контексте представляет собой небольшую, независимую часть программы, которую можно протестировать изолированно от других частей приложения.
Целью модульных тестов является убеждение в том, что каждый компонент работает как задумано и не вызывает ошибок или нежелательного поведения.