

- Главная
- Каталог
- Интернет технологии
- C/C++ | Вопросы собесов
C/C++ | Вопросы собесов
Разбираем вопросы с собеседований на С/С++ разработчика
Статистика канала
Полная статистикаchevron_rightstd::map или std::unordered_map), он должен удовлетворять определённым требованиям.
std::map и std::set используют оператор operator< для сравнения ключей. Это необходимо, чтобы контейнер мог упорядочивать ключи. В этом примере класс MyKey имеет перегруженный оператор operator<, что позволяет использовать его в качестве ключа в std::map.
#include <iostream>
#include <map>
class MyKey {
public:
int value;
MyKey(int v) : value(v) {}
bool operator<(const MyKey& other) const {
return value < other.value;
}
};
int main() {
std::map<MyKey, std::string> myMap;
myMap[MyKey(1)] = "one";
myMap[MyKey(2)] = "two";
for (const auto& pair : myMap) {
std::cout << pair.first.value << ": " << pair.second << std::endl;
}
return 0;
}{}
std::hash для вашего класса.
operator==. В этом примере для класса MyKey определён оператор operator== и специализированный шаблон std::hash, что позволяет использовать его в качестве ключа в std::unordered_map.
#include <iostream>
#include <unordered_map>
#include <functional>
class MyKey {
public:
int value;
MyKey(int v) : value(v) {}
bool operator==(const MyKey& other) const {
return value == other.value;
}
};
namespace std {
template <>
struct hash<MyKey> {
std::size_t operator()(const MyKey& k) const {
return std::hash<int>()(k.value);
}
};
}
int main() {
std::unordered_map<MyKey, std::string> myMap;
myMap[MyKey(1)] = "one";
myMap[MyKey(2)] = "two";
for (const auto& pair : myMap) {
std::cout << pair.first.value << ": " << pair.second << std::endl;
}
return 0;
}{}
Ставь 👍 и забирай 📚 Базу знанийvolatile говорит компилятору, что он не должен оптимизировать код, касающийся этих переменных, и всегда должен считывать их значения непосредственно из памяти.
volatile предотвращает оптимизации, которые могли бы кэшировать значение регистров.
volatile int* port = reinterpret_cast<int*>(0x400);
*port = 42; // Запись в аппаратный регистр {}
volatile гарантирует, что каждое обращение к такой переменной будет действительным.
volatile bool interruptFlag = false;
void interruptHandler() {
interruptFlag = true; // Устанавливается в обработчике прерывания
}
void mainFunction() {
while (!interruptFlag) {
// Ожидание установки флага прерывания
}
// Обработка прерывания
} {}
volatile. Однако следует отметить, что volatile не обеспечивает защиту от гонок данных и не заменяет средства синхронизации, такие как мьютексы или атомарные операции.
volatile bool stopThread = false;
void workerThread() {
while (!stopThread) {
// Выполнение работы
}
}
int main() {
std::thread t(workerThread);
// ...
stopThread = true; // Остановка рабочего потока
t.join();
return 0;
} {}
volatile предотвращает оптимизации компилятором, которые могли бы удалить или кэшировать доступы к переменной.
volatile не обеспечивает потокобезопасность. Для обеспечения корректной работы в многопоточной среде следует использовать мьютексы, атомарные операции или другие механизмы синхронизации.
const volatile, если они не должны изменяться программой, но могут изменяться внешними факторами.
#include <iostream>
volatile int* hardwareRegister = reinterpret_cast<int*>(0x400);
void writeToRegister(int value) {
*hardwareRegister = value; // Запись в регистр
}
int readFromRegister() {
return *hardwareRegister; // Чтение из регистра
}
int main() {
writeToRegister(100);
std::cout << "Register value: " << readFromRegister() << std::endl;
return 0;
}{}
Ставь 👍 и забирай 📚 Базу знаний|). Эта операция позволяет установить конкретный бит в 1, не изменяя остальные биты числа.
|) сравнивает каждый бит двух чисел. Если хотя бы один из битов в соответствующей позиции равен 1, результат в этой позиции будет 1. Иначе, результат будет 0.
n и нули в остальных позициях. Это можно сделать с помощью выражения 1 << n.
x и маской.
#include <iostream>
int main() {
int x = 0b00001010; // Число, с которым работаем (10 в десятичной системе)
int n = 3; // Позиция бита, которую хотим установить (начиная с 0)
// Создаём маску с единицей в позиции n
int mask = 1 << n;
// Устанавливаем бит в позиции n
x = x | mask;
// Вывод результата
std::cout << "Результат: " << std::bitset<8>(x) << std::endl; // Двоичный вывод
std::cout << "Результат: " << x << std::endl; // Десятичный вывод
return 0;
}{}
1 << n создает маску, сдвигая 1 влево на n позиций. Например, если n = 3, результат будет 0b00001000. Операция x | mask устанавливает бит в x на позиции n в 1. Если бит в x на позиции n уже был 1, он останется 1, если он был 0, то станет 1.
x было 0b00001010 и n = 3, результат будет:
Маска: 0b00001000
x | mask: 0b00001010 | 0b00001000 = 0b00001010
В результате бит в позиции 3 установлен в 1, и итоговое значение числа в двоичном формате 0b00001010 (десятичное 10).
Ставь 👍 и забирай 📚 Базу знанийstd::string в C++ имеет несколько механизмов оптимизации для повышения производительности и уменьшения расхода памяти. Рассмотрим основные из них.
std::string не выделяет динамическую память, а хранит символы прямо внутри объекта std::string.
Обычно std::string содержит:
- Указатель на динамическую память
- Размер строки
- Вместимость (capacity)
Но если строка короткая, память не выделяется в куче (heap), а данные хранятся прямо внутри объекта std::string.
#include <iostream>
#include <string>
int main() {
std::string small = "Hello"; // Использует SSO
std::string large = "This is a very long string that will not fit SSO"; // Динамическая память
std::cout << "Small string: " << small << "\n";
std::cout << "Large string: " << large << "\n";
}{}
std::string использовал технику Copy-on-Write (COW), где несколько строк могли разделять одну и ту же память, пока одна из них не изменялась.
Почему отказались?
Не потокобезопасно (если один поток меняет строку, другой может получить неожиданные данные). В C++11 было добавлено std::move, которое делает копирование дешевле. SSO делает COW менее нужной.
std::string a = "Hello";
std::string b = a; // Копия не создается, оба указывают на одну память
b[0] = 'X'; // Теперь создаётся отдельная копия{}
std::string теперь можно перемещать с помощью std::move(), передавая владение ресурсом без копирования.
#include <iostream>
#include <string>
int main() {
std::string a = "Hello, world!";
std::string b = std::move(a); // Перемещение, a становится пустой
std::cout << "b: " << b << "\n"; // "Hello, world!"
}{}
.reserve(size), чтобы избежать многократных перевыделений памяти.
std::string str;
str.reserve(100); // Сразу выделяет память на 100 символов
for (int i = 0; i < 100; i++) {
str += 'a'; // Не перевыделяет память 100 раз
}{}
Ставь 👍 и забирай 📚 Базу знанийОтзывы канала
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
C/C++ | Вопросы собесов — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 4.3K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 5.2, количество отзывов – 1, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 4615.38 ₽, а за 3 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий