C/C++ | Вопросы собесов
رفتن به کانال در Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
نمایش بیشتر4 192
مشترکین
+224 ساعت
+17 روز
+1630 روز
آرشیو پست ها
🤔 Какие есть виды полиморфизма?
В программировании, включая C++, полиморфизм (многоформенность) – это способность объекта или функции принимать разные формы. Полиморфизм является ключевой концепцией объектно-ориентированного программирования (ООП).
🚩Компиляторный (статический) полиморфизм
Этот вид полиморфизма реализуется во время компиляции. Он достигается с помощью перегрузки функций (function overloading) и перегрузки операторов (operator overloading).
🟠Перегрузка функций
В перегрузке функций одна функция имеет несколько определений с разными параметрами.
#include <iostream>
void print(int value) {
std::cout << "Целое число: " << value << std::endl;
}
void print(double value) {
std::cout << "Вещественное число: " << value << std::endl;
}
void print(const std::string& value) {
std::cout << "Строка: " << value << std::endl;
}
int main() {
print(42); // Вызов функции для int
print(3.14); // Вызов функции для double
print("Привет!"); // Вызов функции для строки
return 0;
}
🟠Перегрузка операторов
Перегрузка операторов позволяет определить, как стандартные операторы работают с пользовательскими типами данных.
#include <iostream>
class Complex {
double real, imag;
public:
Complex(double r, double i) : real(r), imag(i) {}
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
void display() const {
std::cout << real << " + " << imag << "i" << std::endl;
}
};
int main() {
Complex c1(1.0, 2.0), c2(3.0, 4.0);
Complex c3 = c1 + c2; // Используется перегрузка оператора +
c3.display(); // Вывод: 4 + 6i
return 0;
}
🚩Рантаймный (динамический) полиморфизм
Этот вид полиморфизма проявляется во время выполнения программы. Реализуется с использованием виртуальных функций и наследования.
Виртуальные функции
#include <iostream>
class Animal {
public:
virtual void sound() const { // Виртуальная функция
std::cout << "Некоторый звук" << std::endl;
}
};
class Dog : public Animal {
public:
void sound() const override { // Переопределение
std::cout << "Гав-гав" << std::endl;
}
};
class Cat : public Animal {
public:
void sound() const override { // Переопределение
std::cout << "Мяу" << std::endl;
}
};
void makeSound(const Animal& animal) {
animal.sound(); // Динамическое определение, какой sound() вызывать
}
int main() {
Dog dog;
Cat cat;
makeSound(dog); // Вывод: Гав-гав
makeSound(cat); // Вывод: Мяу
return 0;
}
Ставь 👍 и забирай 📚 Базу знанийДолгожданный Solaris KRS в кредит на выгодных условиях
Автозапуск и заводская телематика. Цифровой автомобиль. Оставьте заявку!
Узнать больше
Изучите все условия кредита (займа) на сайте в соответствующем разделе. Оценивайте свои финансовые возможности и риски. Финансовые услуги оказывает: ПАО "Совкомбанк", СПАО "Ингосстрах" и другие.
#реклама
mrqz.me
О рекламодателе
🤔 Что пришло на смену auto_ptr?
На смену auto_ptr пришли умные указатели unique_ptr и shared_ptr. unique_ptr безопаснее управляет памятью и исключает случайное копирование, что было проблемой в auto_ptr. Эти новые указатели входят в стандарт C++11 и являются более надежными.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
🤔 Каким свойством должен обладать объект, чтобы его можно было добавить в ассоциативные контейнеры в качестве ключа?
Чтобы объект можно было использовать в качестве ключа в ассоциативных контейнерах (
std::set, std::map, std::unordered_set, std::unordered_map), он должен обладать определёнными свойствами, которые зависят от типа контейнера.
🚩Требования к объекту-ключу
🟠Для `std::map` и `std::set` (красно-чёрное дерево)
Класс или структура, используемая в качестве ключа, должна поддерживать операцию < (меньше).
#include <iostream>
#include <map>
struct Person {
std::string name;
int age;
// Оператор сравнения, необходимый для std::map и std::set
bool operator<(const Person& other) const {
return age < other.age; // Ключи будут упорядочены по возрасту
}
};
int main() {
std::map<Person, std::string> people;
people[{ "Alice", 30 }] = "Doctor";
people[{ "Bob", 25 }] = "Engineer";
for (const auto& [key, value] : people) {
std::cout << key.name << " (" << key.age << "): " << value << '\n';
}
}
🟠Для `std::unordered_map` и `std::unordered_set` (хеш-таблица)
Объект-ключ должен поддерживать операции:
Оператор == (для проверки равенства)
Функция-хешер (по умолчанию std::hash<T>)
#include <iostream>
#include <unordered_map>
struct Person {
std::string name;
int age;
// Оператор равенства нужен для сравнения ключей
bool operator==(const Person& other) const {
return name == other.name && age == other.age;
}
};
// Специализация std::hash для структуры Person
namespace std {
template <>
struct hash<Person> {
std::size_t operator()(const Person& p) const {
return std::hash<std::string>()(p.name) ^ (std::hash<int>()(p.age) << 1);
}
};
}
int main() {
std::unordered_map<Person, std::string> people;
people[{ "Alice", 30 }] = "Doctor";
people[{ "Bob", 25 }] = "Engineer";
for (const auto& [key, value] : people) {
std::cout << key.name << " (" << key.age << "): " << value << '\n';
}
}
Ставь 👍 и забирай 📚 Базу знанийИщу желающих заполнять карточки товаров на ВБ!
Работа полностью на удаленке с зп от 3-5 тыс. рублей в день.
Без опыта, нужен только телефон, занятость 3-6 часов в день.
Всему обучат на бесплатном курсе и после возьму на работу.
Как проходят уроки:
✅ 3 дня уроков по 30 минут
✅ Домашки с проверкой и оплатой бонусами
✅ Плачу 10 тыс за каждую выполненную домашку
Все кто пройдет курс, получат сертификат от школы с образовательной лицензией.
⚡ Места ограничены. Набор может закрыться в любой момент.
👍 Жмите "Зарегистрироваться", чтобы успеть занять место.
Зарегистрироваться
#реклама 16+
course.wildcard.ru
О рекламодателе
🤔 Зачем нам нужна move семантика?
Move семантика введена с целью повышения эффективности работы с ресурсами, такими как память, файлы, сокеты и другие объекты, которые занимают значительные ресурсы. Она позволяет избежать ненужного копирования объектов, что может быть дорогостоящим как по времени, так и по памяти.
🚩Зачем она нужна?
🟠Эффективность работы с ресурсами
Копирование больших объектов может быть очень затратным. Move семантика позволяет перенести ресурсы от одного объекта к другому без дорогостоящего копирования.
🟠Улучшение производительности
Перемещение (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;
}
Ставь 👍 и забирай 📚 Базу знанийIT-инфраструктура под ключ с поддержкой Yandex Cloud
Спроектируем, запустим и возьмём на сопровождение. Экспертиза целой команды без найма в штат.
💰Новым клиентам — грант на облачные сервисы, платите только за работу специалистов.
Оставьте заявку на сайте: подберём партнёра и рассчитаем стоимость.
Получить консультацию
#реклама 16+
yandex.cloud
О рекламодателе
🤔 Чисто виртуальный метод зачем он нужен и какой синтаксис?
Чисто виртуальный метод в C++ определяет интерфейс для производных классов без предоставления реализации. Синтаксис: `virtual ReturnType MethodName() = 0;`. Класс, содержащий чисто виртуальные методы, становится абстрактным, и его нельзя инстанцировать напрямую.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Регистрируйтесь на Yandex Scale 2026
Главная конференция Yandex Cloud.
Узнайте о сервисах, которые меняют ваш бизнес.
4 офлайн-трека (AI, Infra + DevTools, Data, Security), онлайн-трек Deep Tech, воркшопы по ИИ и интерактивы. Подробнее о программе читайте в карточках🗒
📅24 сентября
🚗Москва + 💻онлайн
Участие бесплатное!
Зарегистрироваться
#реклама 16+
scale.yandex.cloud
О рекламодателе
🤔 В какой момент принимается решение, что хеш таблице надо перестроиться?
Решение о необходимости перестроения (рехеширования) хэш-таблицы принимается на основе значения нагрузки (load factor). Нагрузка — это отношение количества элементов в хэш-таблице к количеству бакетов (размеру массива).
🚩Порог нагрузки
Для каждой хэш-таблицы обычно определяется пороговое значение нагрузки. Когда фактическая нагрузка превышает это пороговое значение, происходит рехеширование.
Формула нагрузки:
\text{load factor} = \frac{\text{number of elements}}{\text{size of table}}
Типичные пороговые значения: Пороговое значение нагрузки часто устанавливается в пределах от 0.5 до 1.0, в зависимости от реализации. Например, std::unordered_map в стандартной библиотеке C++ по умолчанию использует пороговое значение 1.0.
🚩Процесс рехеширования
1⃣Увеличение размера таблицы
Размер массива увеличивается, часто в два раза.
2⃣Перераспределение элементов
Все существующие элементы перераспределяются в новую таблицу с использованием новой хэш-функции или той же хэш-функции, но с новым размером таблицы.
🚩Пример
#include <iostream>
#include <list>
#include <vector>
class HashTable {
private:
int currentSize;
int numberOfElements;
double loadFactorThreshold;
std::vector<std::list<std::pair<int, std::string>>> table;
void rehash() {
int oldSize = currentSize;
currentSize *= 2; // Увеличиваем размер таблицы
std::vector<std::list<std::pair<int, std::string>>> newTable(currentSize);
for (const auto& list : table) {
for (const auto& pair : list) {
int hashValue = pair.first % currentSize;
newTable[hashValue].emplace_back(pair.first, pair.second);
}
}
table = std::move(newTable);
}
public:
HashTable(int size = 10, double threshold = 0.75)
: currentSize(size), numberOfElements(0), loadFactorThreshold(threshold) {
table.resize(currentSize);
}
int hashFunction(int key) {
return key % currentSize;
}
void insertItem(int key, std::string value) {
int hashValue = hashFunction(key);
table[hashValue].emplace_back(key, value);
numberOfElements++;
// Проверяем, нужно ли выполнять рехеширование
if (static_cast<double>(numberOfElements) / currentSize > loadFactorThreshold) {
rehash();
}
}
void displayTable() {
for (int i = 0; i < currentSize; i++) {
if (!table[i].empty()) {
std::cout << "Bucket " << i << ": ";
for (auto& pair : table[i]) {
std::cout << "[" << pair.first << ": " << pair.second << "] ";
}
std::cout << std::endl;
}
}
}
};
int main() {
HashTable ht;
ht.insertItem(1, "one");
ht.insertItem(2, "two");
ht.insertItem(11, "eleven"); // Триггер рехеширования при необходимости
ht.displayTable();
// Вывод:
// Bucket 1: [1: one]
// Bucket 2: [2: two]
// Bucket 11: [11: eleven]
return 0;
}
🚩Когда происходит
Рехеширование обычно инициируется в момент, когда после добавления нового элемента нагрузка превышает установленное пороговое значение. Это гарантирует, что хэш-таблица будет эффективно обрабатывать операции поиска, вставки и удаления, поддерживая амортизированное постоянное время для этих операций.
Ставь 👍 и забирай 📚 Базу знанийКак PostgreSQL ведёт себя под большой нагрузкой
Борьба с блокировками в PostgreSQL: как сохранить параллельность при высокой нагрузке.
📅 8 сентября, 20:00 МСК - открытый урок курса «Высоконагруженные системы: архитектура и масштабирование».
📚 Разберём блокировки на уровне транзакций и строк, научимся выявлять взаимные блокировки и узкие места. На реальных примерах покажем оптимизацию запросов и архитектурные приёмы для поддержания производительности.
Для разработчиков, архитекторов, инженеров, DBA и аналитиков, работающих с PostgreSQL.
Регистрируйтесь - получите практические приёмы и спецусловия на обучение. 😊
Узнать больше
#реклама 16+
otus.ru
О рекламодателе
🤔 Альтернативное решение для хранения float цены в качестве ключа?
Вместо хранения float можно:
1.Преобразовать цену в целочисленное значение (например, умножить на 100 или 1000 для точности до копеек/центов).
2.Хранить результат как int, что обеспечит точное сравнение и отсутствие ошибок округления.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
🤔 Какой подсчет ссылок имеется в shared_ptr?
В умном указателе shared_ptr используется два основных счётчика: счётчик сильных ссылок (strong reference count) и счётчик слабых ссылок (weak reference count). Эти счётчики управляют жизненным циклом объекта и связанных с ним ресурсов различными способами.
🚩Счётчик сильных ссылок
Увеличивается каждый раз, когда новый
shared_ptr создаётся как копия другого shared_ptr или когда объект присваивается shared_ptr. Этот счётчик уменьшается, когда shared_ptr уничтожается или когда его значение присваивается другому объекту. Когда счётчик достигает нуля, это означает, что больше нет shared_ptr, управляющих этим объектом, и объект удаляется. Это гарантирует, что ресурсы, связанные с объектом, будут освобождены только тогда, когда не останется ни одной "сильной" ссылки.
🚩Счётчик слабых ссылок
Используется вместе с weak_ptr, другим типом умных указателей, который может ссылаться на объект, управляемый shared_ptr, но не увеличивает счётчик сильных ссылок. Слабые ссылки не предотвращают удаление объекта, к которому они имеют доступ, так как не участвуют в владении объектом. Счётчик слабых ссылок увеличивается каждый раз, когда создаётся weak_ptr, указывающий на объект, и уменьшается, когда такой weak_ptr уничтожается. Когда счётчик сильных ссылок достигает нуля и объект удаляется, память, выделенная под сам объект, освобождается, но "control block" (блок управления), содержащий счётчики, сохраняется до тех пор, пока счётчик слабых ссылок также не обнулится.
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp1 = std::make_shared<int>(10);
std::cout << "sp1 use_count: " << sp1.use_count() << '\n'; // Вывод: 1
{
std::shared_ptr<int> sp2 = sp1; // Копирование shared_ptr
std::cout << "sp1 use_count after copy: " << sp1.use_count() << '\n'; // Вывод: 2
std::weak_ptr<int> wp1 = sp1; // Создание weak_ptr
std::cout << "wp1 use_count: " << wp1.use_count() << '\n'; // Вывод: 2
} // sp2 выходит из области видимости, use_count уменьшается до 1
std::cout << "sp1 use_count after sp2 destruction: " << sp1.use_count() << '\n'; // Вывод: 1
return 0;
}
Ставь 👍 и забирай 📚 Базу знанийБесплатный курс по дизайну в FIGMA от Yudaev School
Онлайн-программа с наставником и чатом.
Внимание! 80% практики.
✅По результату обучения у вас будет портфолио из нескольких работ.
✅Сертификат о прохождении курса.
✅Возможность пройти полное обучение и получить карьерное сопровождение!
Учитесь дизайну у профессионалов в Yudaev Shool.
Переходи по кнопки: "Подробнее" и начинай свое обучение.
Доступ 0 руб.
Узнать больше
#реклама 16+
yudaevschool24.online
О рекламодателе
🤔 В каких STL контейнерах внутри находится хеш таблица?
🚩В стандартной библиотеке шаблонов (STL) C++ хеш-таблица используется для реализации следующих контейнеров
🟠std::unordered_map
Ассоциативный контейнер, который хранит пары ключ-значение, с уникальными ключами. Обеспечивает амортизированное среднее время доступа, вставки и удаления за O(1).
🟠std::unordered_multimap
Ассоциативный контейнер, который хранит пары ключ-значение, где ключи могут повторяться. Обеспечивает амортизированное среднее время для основных операций за O(1), несмотря на дублирование ключей.
🟠std::unordered_set
Ассоциативный контейнер, который хранит уникальные элементы, неупорядоченные. Обеспечивает амортизированное среднее время для основных операций за O(1).
🟠std::unordered_multiset
Ассоциативный контейнер, который хранит элементы, где значения могут повторяться, неупорядоченные. Обеспечивает амортизированное среднее время для основных операций за O(1), несмотря на дублирование элементов.
Ставь 👍 и забирай 📚 Базу знаний
🤔 Сложность удаление из конца у vector?
Удаление элемента из конца vector выполняется за O(1), поскольку не требуется сдвигать элементы. Это делает vector эффективным для операций добавления и удаления в конце. Операции вставки и удаления в конце vector работают за постоянное время, если не требуется перераспределение памяти.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Выигрывайте призы от Яндекс Образования
Популярные блогеры и студенты ЯО делают что-то новое — и у них получается очень вдохновляюще! Общайтесь с любимыми блогерами и выигрывайте призы
Узнать больше
#реклама 16+
refer.id
О рекламодателе
🤔 Строгая гарантия исключений?
Гарантии безопасности исключений (exception safety) в C++ бывают трёх уровней:
Базовая гарантия (Basic Guarantee) – программа не падает, но состояние может быть некорректным.
Строгая гарантия (Strong Guarantee) – либо операция завершается успешно, либо объект остаётся в исходном состоянии.
Гарантия отсутствия исключений (No-throw Guarantee) – операция никогда не бросает исключения.
🚩Что такое строгая гарантия исключений?
Строгая гарантия исключений означает, что если во время выполнения метода выбросится исключение, объект останется в том же состоянии, в каком был до вызова метода.
#include <iostream>
#include <vector>
class BadContainer {
std::vector<int> data;
public:
void add(int value) {
data.push_back(value); // push_back() может выбросить исключение
}
void print() {
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
}
};
int main() {
BadContainer c;
c.add(1);
c.add(2);
c.add(3);
c.print(); // Вывод: 1 2 3
try {
c.add(42); // Может выбросить исключение (например, при нехватке памяти)
} catch (...) {
std::cout << "Ошибка!" << std::endl;
}
c.print(); // ?? Возможно, состояние испорчено!
}
🚩Как реализовать строгую гарантию?
Чтобы добиться строгой гарантии, используем Copy & Swap:
1. Создаём временный объект.
2. Выполняем изменения на временном объекте.
3. Если всё прошло успешно – меняем указатель (swap).
#include <iostream>
#include <vector>
class SafeContainer {
std::vector<int> data;
public:
void add(int value) {
std::vector<int> temp = data; // Копируем текущее состояние
temp.push_back(value); // Изменяем копию
std::swap(data, temp); // Если исключения нет, меняем данные
}
void print() {
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
}
};
int main() {
SafeContainer c;
c.add(1);
c.add(2);
c.add(3);
c.print(); // Вывод: 1 2 3
try {
c.add(42); // Если тут исключение, объект не изменится
} catch (...) {
std::cout << "Ошибка!" << std::endl;
}
c.print(); // Вывод: 1 2 3 (не испорчен!)
}
🚩Где ещё применяется строгая гарантия?
Операции присваивания (operator=) с Copy & Swap
Функции, изменяющие состояние контейнеров (std::vector::resize, std::map::insert)
Операции перевыделения памяти
Функции стандартной библиотеки (std::sort)
Ставь 👍 и забирай 📚 Базу знаний🤔 Асимптотическая сложность в list?
std::list — это двусвязный список, где каждый элемент хранит ссылку на предыдущий и следующий элементы. Это даёт эффективное добавление и удаление элементов в любой части списка, но делает доступ по индексу медленным
🚩Разбор операций в `std::list` с примерами
Добавление в начало и конец — O(1)
std::list<int> lst;
lst.push_back(10); // O(1)
lst.push_front(5); // O(1)
Доступ по индексу — O(n)
auto it = std::next(lst.begin(), 2); // O(n), приходится идти от начала
std::cout << *it << std::endl;
Вставка и удаление по итератору — O(1)
auto it = lst.begin();
std::advance(it, 1); // Двигаем итератор на 1 элемент (O(n))
lst.insert(it, 8); // O(1), просто меняем указатели
lst.erase(it); // O(1), просто изменяем ссылки соседних элементов
Поиск элемента — O(n)
auto it = std::find(lst.begin(), lst.end(), 8); // O(n)
Сортировка — O(n log n)
lst.sort(); // O(n log n), потому что используется сортировка слиянием
Ставь 👍 и забирай 📚 Базу знаний🤔 Что такое абстрактный класс?
Это класс, который содержит хотя бы одну чисто виртуальную функцию. Он не может быть создан как объект и предназначен для использования в качестве базового класса. Такие классы служат для определения интерфейсов и полиморфного поведения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
