C/C++ | Вопросы собесов
Разбираем вопросы с собеседований на С/С++ разработчика. Сайт: easyoffer.ru Реклама: @easyoffer_adv
Більше3 224
Підписники
+124 години
+1997 днів
+1 07130 днів
- Підписники
- Перегляди допису
- ER - коефіцієнт залучення
Триває завантаження даних...
Приріст підписників
Триває завантаження даних...
🤔 Что означает ключевое слово `volatile` в C++?Anonymous voting
- Переменная потоконезависимая
- Переменная только для чтения
- Переменная может изменяться
- Переменная безопасна для потоков
Как можно хранить денежный эквивалент используя int ?
Спросят с вероятностью 17%
Хранение денежных значений с использованием целочисленных типов данных (
int
, long
, int64_t
) — это надежный и распространенный способ избежать проблем с точностью, присущих числам с плавающей точкой. Основная идея состоит в том, чтобы хранить деньги в минимальных единицах валюты, таких как центы для долларов или копейки для рублей.
Допустим, у нас есть цена в долларах и центах. Вместо использования float
или double
, мы можем хранить цену в целых числах, представляющих количество центов. Например, цена $12.99 будет храниться как 1299 центов.
Пример кода
#include <iostream>
#include <iomanip> // Для управления выводом
class Money {
public:
// Конструктор принимает цену в долларах и центах
Money(int dollars, int cents) : totalCents(dollars * 100 + cents) {}
// Конструктор принимает цену в виде float
explicit Money(float amount) : totalCents(static_cast<int>(amount * 100 + 0.5f)) {}
// Получение долларов и центов из totalCents
int getDollars() const {
return totalCents / 100;
}
int getCents() const {
return totalCents % 100;
}
// Вывод цены
void print() const {
std::cout << "$" << getDollars() << "."
<< std::setw(2) << std::setfill('0') << getCents() << std::endl;
}
// Перегрузка операторов для арифметических операций
Money operator+(const Money& other) const {
return Money(0, totalCents + other.totalCents);
}
Money operator-(const Money& other) const {
return Money(0, totalCents - other.totalCents);
}
private:
int totalCents;
};
int main() {
Money price1(12, 99); // $12.99
Money price2(7, 50); // $7.50
Money total = price1 + price2;
std::cout << "Цена 1: ";
price1.print();
std::cout << "Цена 2: ";
price2.print();
std::cout << "Общая цена: ";
total.print();
return 0;
}
Объяснение
1️⃣Класс Money:
✅Хранит сумму денег в виде целого числа (totalCents
), представляющего количество центов.
2️⃣Конструкторы:
✅Один конструктор принимает доллары и центы отдельно.
✅Другой конструктор принимает float
значение и преобразует его в центы.
3️⃣Методы getDollars и getCents:
✅Позволяют получить доллары и центы из общего количества центов.
4️⃣Метод print:
✅Выводит цену в формате $доллары.центы, используя манипуляторы вывода для форматирования.
5️⃣Перегрузка операторов:
✅Перегруженные операторы + и - позволяют выполнять арифметические операции с объектами Money.
Преимущества использования целых чисел для хранения денежных значений
1️⃣Точность:
✅Нет проблем с ошибками округления, как у чисел с плавающей точкой.
2️⃣Простота:
✅Арифметические операции с целыми числами проще и быстрее.
3️⃣Безопасность:
✅Нет потерь точности при конвертации между двоичной и десятичной системами.
Использование целых чисел для хранения денежных значений является надежным и эффективным способом избежать проблем с точностью. Это особенно важно для финансовых приложений, где точность вычислений критически важна. Хранение денег в минимальных единицах валюты (центах или копейках) обеспечивает точность и простоту операций.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 434 вопроса на C/C++ разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых👍 5🔥 2
Фото недоступнеДивитись в Telegram
⚡️В сети начали находить курсы и книги известных онлайн школ в открытом доступе
Вот отсортированная база с тонной материала(постепенно пополняется):
🔗 БАЗА (3385 видео):
(343 видео, 87 книги) — Java
(176 видео, 32 книги) — Git
(293 видео, 63 книги) — C#
(352 видео, 89 книги) — С++
(167 видео, 53 книги) — PHP
(227 видео, 83 книги) — SQL
(163 видео, 29 книги) — Linux
(363 видео, 122 книги) — Python
(415 видео, 168 книги) — Frontend
(143 видео, 33 книги) — Flask
(167 видео, 43 книги) — Django
(197 видео, 49 книги) — Разработка ботов
(137 видео, 93 книги) — Data Science
(113 видео, 82 книги) — GameDev
(129 видео, 73 книги) — QA
Скачивать ничего не нужно — все выложили в Telegram и на YouTube с доступом по ссылке
❤ 1
🤔 Какой оператор C++ не поддерживает?Anonymous voting
- goto
- sizeof
- instanceof
- new
🤯 6❤ 3
Что известно о spinlock и deadlock ?
Спросят с вероятностью 17%
spinlock и deadlock описывают различные аспекты управления доступом к ресурсам и синхронизации. Оба эти термина относятся к блокировкам, но имеют существенно разные цели и поведение.
Spinlock — это один из простейших механизмов блокировки, который активно ожидает освобождения блокировки, постоянно проверяя её состояние в цикле. Это "занятное ожидание" (busy waiting) продолжается до тех пор, пока другой поток не освободит блокировку.
Основные особенности:
✅Производительность: Полезен в ситуациях, где блокировка не будет удерживаться долго, и затраты на активное ожидание оправданы, поскольку это может быть быстрее, чем обращение к механизмам планировщика ОС для управления блокировками.
✅Ресурсоёмкость: Использование его может быть ресурсоёмким, так как поток, ожидающий освобождения блокировки, постоянно занимает процессорное время.
✅Применение: Часто используется в ядрах операционных систем и в сценариях, где потоки выполняются на отдельных процессорах или ядрах, что минимизирует влияние активного ожидания на общую производительность системы.
Deadlock (взаимная блокировка) — это ситуация в многопоточке, когда два или более процессов бесконечно ожидают ресурсы, занятые друг другом, что приводит к полной остановке выполнения задач.
Основные особенности:
✅Условия возникновения: Для возникновения взаимной блокировки должны быть выполнены четыре условия: взаимное исключение (mutual exclusion), удержание и ожидание (hold and wait), отсутствие отзыва (no preemption), и круговое ожидание (circular wait).
✅Решение проблемы: Избежать его можно путём предотвращения одного или нескольких из этих условий. Например, можно устранить круговое ожидание, упорядочивая порядок, в котором потоки могут захватывать блокировки.
✅Обнаружение и восстановление: Операционные системы и некоторые разработчики приложений используют различные алгоритмы для обнаружения и восстановления после взаимной блокировки, включая принудительное завершение одного из застрявших процессов.
Spinlock и deadlock имеют важное значение в многопоточном программировании. Spinlock используется для коротких операций блокировки, где накладные расходы на планирование и переключение контекста могут превысить затраты на активное ожидание. Deadlock является критической проблемой, которая может привести к остановке приложений и требует тщательного проектирования и управления для её предотвращения.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 434 вопроса на C/C++ разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых
🤔 4👍 1
🤔 Что делает оператор `dynamic_cast<>` в C++?Anonymous voting
- Преобразует типы во время компиляции
- Преобразует указатели на классы по иерархии
- Изменяет размер массива
- Генерирует исключения
👀 4👍 1
Зачем нам нужна move семантика ?
Спросят с вероятностью 17%
Move семантика введена с целью повышения эффективности работы с ресурсами, такими как память, файлы, сокеты и другие объекты, которые занимают значительные ресурсы. Она позволяет избежать ненужного копирования объектов, что может быть дорогостоящим как по времени, так и по памяти.
Зачем она нужна?
1️⃣Эффективность работы с ресурсами: Копирование больших объектов может быть очень затратным. Move семантика позволяет перенести ресурсы от одного объекта к другому без дорогостоящего копирования.
2️⃣Улучшение производительности: Перемещение (move) быстрее копирования, поскольку оно всего лишь переназначает указатели на ресурсы, вместо создания их копий. Это особенно важно в приложениях с высокой производительностью, таких как игры, обработка видео, базы данных.
Как это используется?
Move семантика реализуется с помощью rvalue ссылок (ссылок на временные объекты) и специальных методов — move конструктора и move оператора присваивания.
Пример кода:
#include <iostream>
#include <vector>
class MyClass {
public:
int* data;
size_t size;
// Конструктор
MyClass(size_t s) : size(s), data(new int[s]) {
std::cout << "Constructing MyClass\n";
}
// Деструктор
~MyClass() {
delete[] data;
std::cout << "Destructing MyClass\n";
}
// Move конструктор
MyClass(MyClass&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr; // Обнуляем указатель у "старого" объекта
other.size = 0;
std::cout << "Move constructing MyClass\n";
}
// Move оператор присваивания
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data; // Освобождаем старый ресурс
data = other.data;
size = other.size;
other.data = nullptr; // Обнуляем указатель у "старого" объекта
other.size = 0;
std::cout << "Move assigning MyClass\n";
}
return *this;
}
};
int main() {
MyClass a(10); // Создаем объект a
MyClass b = std::move(a); // Перемещаем ресурсы от a к b
return 0;
}
Объяснение кода:
1️⃣Конструктор: Создает объект с заданным размером.
2️⃣Деструктор: Освобождает ресурсы.
3️⃣Move конструктор: Перемещает ресурсы от одного объекта к другому, обнуляя указатели на ресурсы у старого объекта.
4️⃣Move оператор присваивания: Аналогично move конструктору, но используется для уже существующих объектов.
Move семантика нужна для повышения производительности и эффективности работы с ресурсами. Она позволяет перемещать ресурсы между объектами без их копирования, что экономит время и память.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 434 вопроса на C/C++ разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых👍 4😁 1
🤔 Какой механизм в C++ используется для прямого управления памятью?Anonymous voting
- Гарбаж коллектор
- Автоматическое выделение
- new и delete
- Smart pointers
👍 5🔥 1
Что известно про placement new ?
Спросят с вероятностью 17%
placement new — это разновидность оператора
new
, который позволяет конструировать объекты в предварительно выделенной области памяти. Это особенно полезно в случаях, когда необходимо точно контролировать, где объект должен быть расположен в памяти, или когда нужно избежать лишних выделений памяти для повышения производительности или из-за ограничений среды выполнения.
Основные принципы и использование
Не выделяет память. Вместо этого он использует указатель на уже выделенную область памяти, чтобы инициализировать объект в этом месте. Для этого требуется передать в new
адрес, где должен быть размещен объект.
Синтаксис выглядит следующим образом:
#include <new> // Необходим для std::nothrow и std::placement_new
char buffer[sizeof(MyClass)];
MyClass* pMyClass = new (buffer) MyClass();
В этом примере объект типа MyClass
создается непосредственно в буфере, предоставленном пользователем. Это означает, что память для объекта не выделяется динамически через стандартный механизм выделения памяти, а используется область, указанная пользователем.
Преимущества и особенности
1️⃣Контроль расположения: Позволяет разработчикам выбирать, где именно в памяти будет расположен объект. Это может быть критически важно для систем, требующих определенного выравнивания или расположения объектов для оптимизации производительности.
2️⃣Избежание дополнительного выделения памяти: При его использовании можно повторно использовать или эффективно управлять памятью, что может быть важно в системах с ограниченными ресурсами или в высокопроизводительных приложениях.
3️⃣Конструирование объектов на месте: Полезно для создания объектов внутри предварительно выделенных массивов или сложных структур данных, как например, в памяти, выделенной для контейнеров.
Осторожность при использовании
✅Управление памятью: Поскольку он не освобождает память автоматически, разработчики должны вручную вызывать деструктор для любых объектов, созданных с помощью placement new
, когда объекты больше не нужны.
✅Исключения и безопасность: Нужно быть внимательным при обработке исключений в конструкторах объектов, созданных через placement new
, чтобы избежать утечек ресурсов.
pMyClass->~MyClass();
Это необходимо, поскольку delete
не может быть использован с объектами, созданными с помощью placement new
.
Placement new
— это мощный инструмент, предоставляющий гибкость в управлении памятью и расположении объектов. Он особенно полезен в ситуациях, когда требуется оптимизация производительности или когда работа ведется в средах с ограниченными ресурсами. Однако его использование требует тщательного управления жизненным циклом объекта и явного вызова деструкторов.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 434 вопроса на C/C++ разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых👍 7
Какой есть механизм атомарного залочивания двух mutex ?
Спросят с вероятностью 17%
Атомарное залочивание двух (или более) мьютексов — это сложная задача, поскольку неправильная реализация может привести к взаимоблокировке (deadlock). Взаимоблокировка возникает, когда два потока ждут освобождения мьютексов, которые друг у друга заняты. Для решения этой проблемы используется несколько методов. Один из них — использование стандартной функции
std::lock
из C++11, которая позволяет атомарно залочить несколько мьютексов.
std::lock
Гарантирует, что все переданные ей мьютексы будут залочены без возможности возникновения взаимоблокировки. Если один из мьютексов не может быть залочен, функция разблокирует уже захваченные мьютексы и начнет попытку захвата заново.
Пример кода:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex m1, m2;
void threadFunction1() {
std::lock(m1, m2); // атомарное залочивание
std::lock_guard<std::mutex> lg1(m1, std::adopt_lock);
std::lock_guard<std::mutex> lg2(m2, std::adopt_lock);
// Критическая секция
std::cout << "Thread 1 has locked both mutexes" << std::endl;
// мьютексы автоматически разблокируются при выходе из области видимости
}
void threadFunction2() {
std::lock(m1, m2); // атомарное залочивание
std::lock_guard<std::mutex> lg1(m1, std::adopt_lock);
std::lock_guard<std::mutex> lg2(m2, std::adopt_lock);
// Критическая секция
std::cout << "Thread 2 has locked both mutexes" << std::endl;
// мьютексы автоматически разблокируются при выходе из области видимости
}
int main() {
std::thread t1(threadFunction1);
std::thread t2(threadFunction2);
t1.join();
t2.join();
return 0;
}
Объяснение кода:
1️⃣std::lock(m1, m2): Эта функция пытается залочить оба мьютекса одновременно. Если это не удается (например, если один мьютекс уже захвачен другим потоком), то освобождаются все захваченные мьютексы и начинается новая попытка захвата.
2️⃣std::lock_guard<std::mutex> lg1(m1, std::adopt_lock): Эта конструкция создает объект std::lock_guard
, который автоматически разблокирует мьютекс при выходе из области видимости. Параметр std::adopt_lock
указывает, что мьютекс уже захвачен и не должен быть захвачен повторно.
3️⃣Критическая секция: Между захватом и освобождением мьютексов располагается код, который должен выполняться безопасно в многопоточной среде.
Для атомарного захвата двух мьютексов используется функция std::lock
, которая предотвращает взаимоблокировки. Это позволяет безопасно управлять ресурсами в многопоточной среде.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 434 вопроса на C/C++ разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых👍 9🔥 1
Оберіть інший тариф
На вашому тарифі доступна аналітика тільки для 5 каналів. Щоб отримати більше — оберіть інший тариф.