❓ Вопрос на собеседовании
Что такое emplace в C++ и чем оно отличается от push_back при работе с контейнерами STL?
Ответ ⬇️
Метод emplace добавляет новый элемент в контейнер, создавая его непосредственно на месте, вместо создания временного объекта и его копирования (как в случае с push_back). Это повышает производительность, особенно при добавлении сложных объектов. Метод emplace вызывает конструктор объекта с переданными аргументами прямо в памяти контейнера.
Пример использования ⚙️
#include
#include
#include
class MyClass {
public:
MyClass(const std::string& name, int value) : name(name), value(value) {
std::cout
@quizcpp
Что такое emplace в C++ и чем оно отличается от push_back при работе с контейнерами STL?
Ответ ⬇️
Метод emplace добавляет новый элемент в контейнер, создавая его непосредственно на месте, вместо создания временного объекта и его копирования (как в случае с push_back). Это повышает производительность, особенно при добавлении сложных объектов. Метод emplace вызывает конструктор объекта с переданными аргументами прямо в памяти контейнера.
Пример использования ⚙️
#include
#include
#include
class MyClass {
public:
MyClass(const std::string& name, int value) : name(name), value(value) {
std::cout
@quizcpp
👩💻 Задача по C++: Подсчёт слов в строке
Напишите функцию, которая принимает строку и возвращает количество слов в ней. Слова разделены пробелами, и строки могут содержать несколько подряд идущих пробелов.
Пример:
#include
#include
int main() {
std::string text1 = "Hello world!";
std::string text2 = " Multiple spaces between words ";
std::cout
@quizcpp
Напишите функцию, которая принимает строку и возвращает количество слов в ней. Слова разделены пробелами, и строки могут содержать несколько подряд идущих пробелов.
Пример:
#include
#include
int main() {
std::string text1 = "Hello world!";
std::string text2 = " Multiple spaces between words ";
std::cout
@quizcpp
❓ Вопрос на собеседовании
Что такое умные указатели в C++ (std::unique_ptr, std::shared_ptr, std::weak_ptr), и чем они отличаются друг от друга?
Ответ ⬇️
Умные указатели в C++ автоматизируют управление памятью и помогают избежать утечек памяти. Они находятся в заголовке .
std::unique_ptr владеет ресурсом единолично. При уничтожении указателя ресурс освобождается.
std::shared_ptr позволяет нескольким указателям совместно владеть ресурсом. Ресурс освобождается, когда последний shared_ptr уничтожается.
std::weak_ptr предоставляет доступ к ресурсу, но не увеличивает счётчик ссылок. Используется для предотвращения циклических зависимостей.
Пример использования ⚙️
#include
#include
int main() {
// unique_ptr: единоличное владение
std::unique_ptr uptr = std::make_unique(10);
std::cout
@quizcpp
Что такое умные указатели в C++ (std::unique_ptr, std::shared_ptr, std::weak_ptr), и чем они отличаются друг от друга?
Ответ ⬇️
Умные указатели в C++ автоматизируют управление памятью и помогают избежать утечек памяти. Они находятся в заголовке .
std::unique_ptr владеет ресурсом единолично. При уничтожении указателя ресурс освобождается.
std::shared_ptr позволяет нескольким указателям совместно владеть ресурсом. Ресурс освобождается, когда последний shared_ptr уничтожается.
std::weak_ptr предоставляет доступ к ресурсу, но не увеличивает счётчик ссылок. Используется для предотвращения циклических зависимостей.
Пример использования ⚙️
#include
#include
int main() {
// unique_ptr: единоличное владение
std::unique_ptr uptr = std::make_unique(10);
std::cout
@quizcpp
❌ Антипаттерн недели: Утечка памяти из-за забытых delete
Забыть освободить выделенную память с помощью delete может привести к утечке памяти (memory leak).
Каждый вызов new должен сопровождаться вызовом delete или delete[]. В противном случае выделенная память остаётся занята до завершения программы.
✔️ Как исправить:
Используйте умные указатели (std::unique_ptr или std::shared_ptr), чтобы автоматически управлять памятью. Если используете new, не забудьте вызвать delete.
#include
#include
void createArray() {
auto arr = std::make_unique(5);
arr[0] = 42;
std::cout
@quizcpp
Забыть освободить выделенную память с помощью delete может привести к утечке памяти (memory leak).
Каждый вызов new должен сопровождаться вызовом delete или delete[]. В противном случае выделенная память остаётся занята до завершения программы.
✔️ Как исправить:
Используйте умные указатели (std::unique_ptr или std::shared_ptr), чтобы автоматически управлять памятью. Если используете new, не забудьте вызвать delete.
#include
#include
void createArray() {
auto arr = std::make_unique(5);
arr[0] = 42;
std::cout
@quizcpp
❓ Вопрос на собеседовании
Что такое pimpl idiom в C++ и когда его использовать?
Ответ ⬇️
Pimpl idiom (Pointer to Implementation) — это паттерн, который скрывает реализацию класса за указателем на скрытый тип в заголовочном файле. Это улучшает инкапсуляцию, минимизирует зависимости и ускоряет компиляцию.
Пример использования ⚙️
// MyClass.h
#include
class MyClassImpl; // Forward declaration
class MyClass {
public:
MyClass();
void someFunction();
private:
std::unique_ptr pImpl; // Указатель на скрытую реализацию
};
// MyClass.cpp
#include "MyClass.h"
#include
class MyClassImpl {
public:
void someFunctionImpl() { std::cout someFunctionImpl(); }
// main.cpp
#include "MyClass.h"
int main() {
MyClass obj;
obj.someFunction();
return 0;
}
В этом примере pimpl idiom скрывает реализацию MyClassImpl, что позволяет изменять реализацию без изменения публичного интерфейса, улучшая инкапсуляцию и ускоряя компиляцию.
👩💻
@quizcpp
Что такое pimpl idiom в C++ и когда его использовать?
Ответ ⬇️
Pimpl idiom (Pointer to Implementation) — это паттерн, который скрывает реализацию класса за указателем на скрытый тип в заголовочном файле. Это улучшает инкапсуляцию, минимизирует зависимости и ускоряет компиляцию.
Пример использования ⚙️
// MyClass.h
#include
class MyClassImpl; // Forward declaration
class MyClass {
public:
MyClass();
void someFunction();
private:
std::unique_ptr pImpl; // Указатель на скрытую реализацию
};
// MyClass.cpp
#include "MyClass.h"
#include
class MyClassImpl {
public:
void someFunctionImpl() { std::cout someFunctionImpl(); }
// main.cpp
#include "MyClass.h"
int main() {
MyClass obj;
obj.someFunction();
return 0;
}
В этом примере pimpl idiom скрывает реализацию MyClassImpl, что позволяет изменять реализацию без изменения публичного интерфейса, улучшая инкапсуляцию и ускоряя компиляцию.
👩💻
@quizcpp
❓ Вопрос на собеседовании
Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?
Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки , который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.
Пример использования ⚙️
#include
#include
#include
std::atomic counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout
@quizcpp
Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?
Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки , который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.
Пример использования ⚙️
#include
#include
#include
std::atomic counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout
@quizcpp
❓ Вопрос на собеседовании
Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?
Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки , который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.
Пример использования ⚙️
#include
#include
#include
std::atomic counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout
@quizcpp
Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?
Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки , который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.
Пример использования ⚙️
#include
#include
#include
std::atomic counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout
@quizcpp
❓ Вопрос на собеседовании
Что такое std::allocator в C++, и как его можно использовать для управления памятью?
Ответ ⬇️
std::allocator — это стандартный шаблонный класс, предоставляющий низкоуровневые инструменты для управления памятью в STL-контейнерах. Он позволяет настраивать аллокацию памяти, предоставляя методы для выделения, освобождения и построения объектов.
Пример использования ⚙️
#include
#include
int main() {
std::allocator allocator;
// Выделяем память для 3 целых чисел
int* arr = allocator.allocate(3);
// Конструируем элементы
allocator.construct(arr, 10);
allocator.construct(arr + 1, 20);
allocator.construct(arr + 2, 30);
// Выводим значения
for (int i = 0; i < 3; ++i) {
std::cout
@quizcpp
Что такое std::allocator в C++, и как его можно использовать для управления памятью?
Ответ ⬇️
std::allocator — это стандартный шаблонный класс, предоставляющий низкоуровневые инструменты для управления памятью в STL-контейнерах. Он позволяет настраивать аллокацию памяти, предоставляя методы для выделения, освобождения и построения объектов.
Пример использования ⚙️
#include
#include
int main() {
std::allocator allocator;
// Выделяем память для 3 целых чисел
int* arr = allocator.allocate(3);
// Конструируем элементы
allocator.construct(arr, 10);
allocator.construct(arr + 1, 20);
allocator.construct(arr + 2, 30);
// Выводим значения
for (int i = 0; i < 3; ++i) {
std::cout
@quizcpp
❓ Вопрос на собеседовании
Что такое constexpr в C++ и в чём его отличие от const?
Ответ ⬇️
constexpr — это спецификатор в C++, который указывает, что значение выражения или функции может быть вычислено на этапе компиляции, если это возможно. В отличие от const, который просто запрещает изменение значения, constexpr гарантирует, что вычисления происходят на этапе компиляции (при условии, что все входные данные известны на этом этапе).
constexpr используется для оптимизации кода, особенно в вычислениях, которые можно заранее предсказать.
Пример использования ⚙️
#include
constexpr int square(int x) {
return x * x; // Вычисляется на этапе компиляции
}
int main() {
constexpr int result = square(5); // Результат вычислен на этапе компиляции
std::cout
@quizcpp
Что такое constexpr в C++ и в чём его отличие от const?
Ответ ⬇️
constexpr — это спецификатор в C++, который указывает, что значение выражения или функции может быть вычислено на этапе компиляции, если это возможно. В отличие от const, который просто запрещает изменение значения, constexpr гарантирует, что вычисления происходят на этапе компиляции (при условии, что все входные данные известны на этом этапе).
constexpr используется для оптимизации кода, особенно в вычислениях, которые можно заранее предсказать.
Пример использования ⚙️
#include
constexpr int square(int x) {
return x * x; // Вычисляется на этапе компиляции
}
int main() {
constexpr int result = square(5); // Результат вычислен на этапе компиляции
std::cout
@quizcpp
❓ Вопрос на собеседовании
Что такое Placement new в C++ и как оно используется?
Ответ ⬇️
Placement new — это форма оператора new, которая позволяет разместить объект в заранее выделенной области памяти. Вместо выделения памяти на куче, как это делает обычный new, placement new создаёт объект в памяти, адрес которой передаётся в качестве аргумента.
Это используется для более точного контроля над памятью, например, в реализациях кастомных аллокаторов, пулах памяти или для повышения производительности в системах с ограниченными ресурсами.
Пример использования ⚙️
#include
#include // Для placement new
int main() {
alignas(alignof(int)) char buffer[sizeof(int)]; // Буфер для хранения объекта
int* ptr = new (buffer) int(42); // Размещение объекта в buffer
std::cout
@quizcpp
Что такое Placement new в C++ и как оно используется?
Ответ ⬇️
Placement new — это форма оператора new, которая позволяет разместить объект в заранее выделенной области памяти. Вместо выделения памяти на куче, как это делает обычный new, placement new создаёт объект в памяти, адрес которой передаётся в качестве аргумента.
Это используется для более точного контроля над памятью, например, в реализациях кастомных аллокаторов, пулах памяти или для повышения производительности в системах с ограниченными ресурсами.
Пример использования ⚙️
#include
#include // Для placement new
int main() {
alignas(alignof(int)) char buffer[sizeof(int)]; // Буфер для хранения объекта
int* ptr = new (buffer) int(42); // Размещение объекта в buffer
std::cout
@quizcpp
❓ Вопрос на собеседовании
Как работает zero-cost exceptions в C++ и почему они эффективны?
Ответ ⬇️
Zero-cost exceptions означают, что во время нормального выполнения кода исключения не влияют на производительность. Вместо проверок компилятор создаёт таблицы (.eh_frame в ELF), которые используются только при выбросе исключения. В отличие от if-проверок ошибок, исключения C++ не замедляют код, пока не происходит ошибка.
Пример использования ⚙️
#include
#include
void risky() { throw std::runtime_error("Ошибка!"); }
int main() {
try { risky(); }
catch (const std::exception& e) { std::cout
@quizcpp
Как работает zero-cost exceptions в C++ и почему они эффективны?
Ответ ⬇️
Zero-cost exceptions означают, что во время нормального выполнения кода исключения не влияют на производительность. Вместо проверок компилятор создаёт таблицы (.eh_frame в ELF), которые используются только при выбросе исключения. В отличие от if-проверок ошибок, исключения C++ не замедляют код, пока не происходит ошибка.
Пример использования ⚙️
#include
#include
void risky() { throw std::runtime_error("Ошибка!"); }
int main() {
try { risky(); }
catch (const std::exception& e) { std::cout
@quizcpp
❓ Вопрос на собеседовании
Как работает expression SFINAE в C++, и чем оно отличается от обычного SFINAE?
Ответ ⬇️
SFINAE (Substitution Failure Is Not An Error) позволяет компилятору отбрасывать неподходящие шаблонные перегрузки без генерации ошибок. Expression SFINAE — это техника, когда проверяется не только наличие типа, но и возможность вызова выражения с ним.
Обычный SFINAE работает с typename, а expression SFINAE используется в decltype() для проверки существования конкретных операций или методов в типе.
Пример использования ⚙️
#include
#include
// Проверяем, есть ли у типа метод size()
template
auto has_size(int) -> decltype(std::declval().size(), std::true_type{}) {
return {};
}
template
std::false_type has_size(...) { return {}; }
int main() {
std::cout
@quizcpp
Как работает expression SFINAE в C++, и чем оно отличается от обычного SFINAE?
Ответ ⬇️
SFINAE (Substitution Failure Is Not An Error) позволяет компилятору отбрасывать неподходящие шаблонные перегрузки без генерации ошибок. Expression SFINAE — это техника, когда проверяется не только наличие типа, но и возможность вызова выражения с ним.
Обычный SFINAE работает с typename, а expression SFINAE используется в decltype() для проверки существования конкретных операций или методов в типе.
Пример использования ⚙️
#include
#include
// Проверяем, есть ли у типа метод size()
template
auto has_size(int) -> decltype(std::declval().size(), std::true_type{}) {
return {};
}
template
std::false_type has_size(...) { return {}; }
int main() {
std::cout
@quizcpp
❓ Вопрос на собеседовании
Как работает expression SFINAE в C++, и чем оно отличается от обычного SFINAE?
Ответ ⬇️
SFINAE (Substitution Failure Is Not An Error) позволяет компилятору отбрасывать неподходящие шаблонные перегрузки без генерации ошибок. Expression SFINAE — это техника, когда проверяется не только наличие типа, но и возможность вызова выражения с ним.
Обычный SFINAE работает с typename, а expression SFINAE используется в decltype() для проверки существования конкретных операций или методов в типе.
Пример использования ⚙️
#include
#include
// Проверяем, есть ли у типа метод size()
template
auto has_size(int) -> decltype(std::declval().size(), std::true_type{}) {
return {};
}
template
std::false_type has_size(...) { return {}; }
int main() {
std::cout
@quizcpp
Как работает expression SFINAE в C++, и чем оно отличается от обычного SFINAE?
Ответ ⬇️
SFINAE (Substitution Failure Is Not An Error) позволяет компилятору отбрасывать неподходящие шаблонные перегрузки без генерации ошибок. Expression SFINAE — это техника, когда проверяется не только наличие типа, но и возможность вызова выражения с ним.
Обычный SFINAE работает с typename, а expression SFINAE используется в decltype() для проверки существования конкретных операций или методов в типе.
Пример использования ⚙️
#include
#include
// Проверяем, есть ли у типа метод size()
template
auto has_size(int) -> decltype(std::declval().size(), std::true_type{}) {
return {};
}
template
std::false_type has_size(...) { return {}; }
int main() {
std::cout
@quizcpp