В C++ есть три уровня доступа для членов класса: public, protected и private.
- public: члены класса, помеченные как public, доступны из любого места в программе. Их можно вызвать или изменить из любого контекста.
- protected: члены, помеченные как protected, доступны внутри самого класса, а также в его потомках (классах-наследниках). Однако они недоступны вне этих классов.
- private: приватные члены доступны только внутри самого класса. Ни внешние функции, ни потомки не имеют к ним доступа.
Пример:
class Base {
public:
int publicMember; // Доступен всем
protected:
int protectedMember; // Доступен классу и наследникам
private:
int privateMember; // Доступен только внутри класса Base
};
class Derived : public Base {
public:
void accessMembers() {
publicMember = 1; // OK
protectedMember = 2; // OK
// privateMember = 3; // Ошибка: privateMember недоступен
}
};
void externalFunction() {
Base obj;
obj.publicMember = 1; // OK
// obj.protectedMember = 2; // Ошибка: protectedMember недоступен
// obj.privateMember = 3; // Ошибка: privateMember недоступен
}
Таким образом, выбор уровня доступа определяет, какие части кода могут использовать данные или функции класса.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
1. Выбор эффективных алгоритмов и структур данных. Оптимальный алгоритм может значительно снизить время выполнения и потребление памяти.
2. Включение оптимизаций компилятора. Использование флагов компиляции, таких как
-O2
или -O3
, позволяет генерировать более эффективный машинный код.3. Избегание избыточного копирования. Передача объектов по
const
ссылке или использование std::move
для перемещения ресурсов.
void processData(const std::vector<int>& data); // Передача по константной ссылке
std::vector<int> data = getData();
processData(std::move(data)); // Перемещение данных
4. Использование эффективных контейнеров. Выбор подходящих контейнеров STL, таких как
std::vector
вместо std::list
для последовательного доступа.5. Уменьшение количества динамических выделений памяти. Предпочтение статического или стекового размещения объектов, использование пулов памяти.
6. Инлайн-функции. Использование ключевого слова
inline
для небольших часто вызываемых функций.7. Профилирование кода. Применение инструментов для выявления узких мест и точечной оптимизации.
8. Параллелизация. Использование многопоточности (std::thread) или SIMD-инструкций для распараллеливания вычислений.
9. Избежание виртуальных функций там, где это возможно. Виртуальные вызовы могут быть медленнее из-за динамической диспетчеризации.
10. Оптимизация работы с вводом-выводом. Буферизация операций ввода-вывода и минимизация обращений к диску.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Make — это утилита для автоматизации сборки проектов из исходного кода. Она использует Makefile — специальный файл, в котором описаны правила сборки и зависимости между файлами.
Основная идея Make: при сборке пересобираются только те части проекта, которые были изменены, что ускоряет процесс.
Простой пример Makefile для программы на C++:
# Компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -Wall -std=c++17
# Исполняемый файл
TARGET = program
# Список объектов
OBJS = main.o utils.o
# Цель по умолчанию
all: $(TARGET)
# Правило сборки исполняемого файла
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
# Правило для компиляции main.cpp
main.o: main.cpp utils.h
$(CXX) $(CXXFLAGS) -c main.cpp
# Правило для компиляции utils.cpp
utils.o: utils.cpp utils.h
$(CXX) $(CXXFLAGS) -c utils.cpp
# Очистка сгенерированных файлов
clean:
rm -f $(OBJS) $(TARGET)
В этом Makefile определены:
- Переменные:
CXX
, CXXFLAGS
, TARGET
, OBJS
.- Цели (targets):
all
, $(TARGET)
, main.o
, utils.o
, clean
.- Зависимости: например,
main.o
зависит от main.cpp
и utils.h
.- Команды: команды компиляции и сборки.
Чтобы использовать Makefile:
- Запуск сборки:
make
или make all
.- Очистка файлов:
make clean
.Make автоматически отслеживает временные метки файлов и пересобирает только те части, которые изменились, вместе с зависимостями.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
std::lock_guard и std::unique_lock — оба являются инструментами для управления мьютексами в многопоточном программировании, обеспечивая автоматическую блокировку и разблокировку.
std::lock_guard — простой RAII-объект, который блокирует мьютекс при создании и автоматически разблокирует его при уничтожении. Он не предоставляет возможности контроля над блокировкой после создания.
std::mutex mtx;
void func() {
std::lock_guard<std::mutex> lock(mtx);
// Критическая секция
} // Мьютекс разблокируется автоматически здесь
std::unique_lock — более гибкий RAII-объект, который позволяет управлять блокировкой мьютекса. С его помощью можно:
- Откладывать блокировку (defer locking)
- Разблокировать мьютекс до конца области видимости
- Перемещать объект unique_lock между функциями
std::mutex mtx;
void func() {
std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // Блокировка отложена
// ... некоторые операции
lock.lock(); // Ручная блокировка
// Критическая секция
lock.unlock(); // Ручная разблокировка
// ...
} // Если мьютекс заблокирован, он разблокируется автоматически
Основные отличия:
- Контроль блокировки: std::unique_lock позволяет откладывать блокировку и вручную блокировать/разблокировать мьютекс, тогда как std::lock_guard блокирует сразу и не дает возможности управления.
- Перемещение: std::unique_lock поддерживает перемещение, что позволяет передавать владение блокировкой, std::lock_guard не поддерживает это.
- Накладные расходы: std::unique_lock может быть немного тяжелее std::lock_guard из-за дополнительной функциональности.
Выбор между ними зависит от необходимости: если нужна простая автоматическая блокировка без излишней сложности, подходит std::lock_guard. Для более гибкого управления блокировкой используйте std::unique_lock.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
«Абстрактный класс» в C++ — это класс, содержащий хотя бы одну чисто виртуальную функцию. Такой класс не может быть инстанцирован напрямую и служит основой для создания производных классов, которые реализуют чисто виртуальные функции.
Например:
class Shape {
public:
virtual void draw() = 0; // Чисто виртуальная функция
};
В этом примере
Shape
— абстрактный класс с чисто виртуальной функцией draw()
. Производные классы должны предоставить свою реализацию этой функции:
class Circle : public Shape {
public:
void draw() override {
// Реализация рисования круга
}
};
class Rectangle : public Shape {
public:
void draw() override {
// Реализация рисования прямоугольника
}
};
Абстрактные классы используются для определения интерфейсов и обеспечения полиморфизма. Они позволяют работать с разными объектами через указатель или ссылку на базовый класс, не зная о конкретных реализациях производных классов.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
В C++ для реализации многопоточности используется класс
std::thread
из стандарта C++11. Он позволяет запускать функции в отдельных потоках.Например, запуск функции в новом потоке:
#include <iostream>
#include <thread>
void work() {
// Некоторые действия
std::cout << "Привет из потока!" << std::endl;
}
int main() {
std::thread t(work); // Запуск функции work в новом потоке
t.join(); // Ожидание завершения потока
return 0;
}
В этом примере создается поток
t
, который выполняет функцию work()
. Метод join()
блокирует текущий поток до завершения потока t
.Можно передавать параметры в функцию потока:
void work(int value) {
// Использование переданного значения
std::cout << "Значение: " << value << std::endl;
}
int main() {
int num = 42;
std::thread t(work, num); // Передача аргумента в функцию потока
t.join();
return 0;
}
При работе с потоками важно учитывать доступ к общим ресурсам. Для синхронизации используются мьютексы:
#include <mutex>
std::mutex mtx;
void work() {
mtx.lock(); // Захват мьютекса
// Критическая секция
mtx.unlock(); // Освобождение мьютекса
}
Мьютексы предотвращают одновременный доступ к данным из разных потоков, избегая гонок данных.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
C++ собеседования pinned «Подписывайся на наши новые каналы! 👩💻 Git 🖥 SQL 👩💻 QA»
Makefile используется для автоматизации процесса сборки программ. Основные команды (или правила) в Makefile определяются в формате:
цель: зависимости
команды
Ниже приведен простой Makefile:
all: program
program: main.o utils.o
g++ main.o utils.o -o program # Компоновка объектных файлов в исполняемый файл
main.o: main.cpp
g++ -c main.cpp -o main.o # Компиляция main.cpp в объектный файл
utils.o: utils.cpp
g++ -c utils.cpp -o utils.o # Компиляция utils.cpp в объектный файл
clean:
rm -f *.o program # Удаление объектных файлов и программы
В этом Makefile определены следующие цели:
-
all
: цель по умолчанию, которая зависит от program
.-
program
: зависит от main.o
и utils.o
, осуществляет линковку.-
main.o
и utils.o
: компилируют исходные файлы в объектные.-
clean
: удаляет сгенерированные файлы.Команды выполняются, только если зависимости новее цели. Это обеспечивает эффективную сборку, пересобирая только измененные части кода.
Makefile позволяет автоматизировать и управлять процессом сборки, делая его более организованным и масштабируемым, особенно в больших проектах.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Разница между ссылками и указателями в C++ заключается в их использовании и поведении.
Ссылки являются альтернативными именами для существующих переменных. После инициализации ссылка всегда ссылается на один и тот же объект и не может быть переназначена на другой.
int a = 5;
int& ref = a; // Ссылка на переменную a
ref = 10; // Изменяет значение a на 10
Указатели хранят адреса переменных и могут быть переназначены для указания на другие объекты. Указатель может быть
nullptr
или указывать на неинициализированную память.
int a = 5;
int* ptr = &a; // Указатель на переменную a
*ptr = 10; // Изменяет значение a на 10
int b = 20;
ptr = &b; // Теперь ptr указывает на b
Основные отличия:
- Инициализация: Ссылки должны быть инициализированы при объявлении. Указатели могут быть инициализированы позже или быть
nullptr
.- Переназначение: Ссылки не могут изменить объект, на который ссылаются. Указатели могут переназначаться на другие адреса.
- Нулевые значения: Ссылки не могут быть нулевыми или несвязанными. Указатели могут быть
nullptr
.- Операции разыменования: Для доступа к значению по указателю используется оператор
*
. Ссылки позволяют обращаться к переменной напрямую без специальных операторов.Ссылки обеспечивают более безопасный и простой синтаксис, особенно при передаче параметров в функции. Указатели предоставляют больший контроль и гибкость при работе с памятью, но требуют более тщательного управления для предотвращения ошибок, таких как утечки памяти или разыменование
nullptr
.Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
constexpr
появилась в C++11 и используется для выполнения вычислений на этапе компиляции. Это позволяет создавать константные выражения и оптимизировать код.Пример использования
constexpr
функции:
constexpr int square(int x) {
return x * x;
}
constexpr int value = square(5); // Вычисляется во время компиляции
int array[value]; // Массив размером 25
В этом примере функция
square
вычисляет квадрат числа во время компиляции, и переменная value
получает значение 25.Начиная с C++14,
constexpr
функции могут содержать более сложную логику:
constexpr int factorial(int n) {
return n <= 1 ? 1 : (n * factorial(n - 1));
}
static_assert(factorial(5) == 120, "Неверное вычисление факториала");
Здесь функция
factorial
рекурсивно вычисляет факториал числа во время компиляции.constexpr
может быть применен к переменным:
constexpr double pi = 3.1415926535;
А также к конструкторам и методам классов:
class Point {
public:
constexpr Point(double x, double y) : x_(x), y_(y) {}
constexpr double getX() const { return x_; }
constexpr double getY() const { return y_; }
private:
double x_;
double y_;
};
constexpr Point origin(0.0, 0.0);
Использование
constexpr
позволяет:- Выполнять проверки во время компиляции с помощью
static_assert
.- Улучшать производительность за счет вычислений на этапе компиляции.
- Создавать константные выражения для инициализации констант, размеров массивов и параметров шаблонов.
Важно помнить, что для успешного использования
constexpr
, все функции и выражения внутри него также должны быть constexpr
или доступны на этапе компиляции.Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
std::vector
из стандартной библиотеки C++ предоставляет динамический массив, который может изменять свой размер во время выполнения и автоматически управляет памятью. Ниже представлены основные способы использования std::vector
и его методов.Объявление и инициализация:
#include <vector>
std::vector<int> vec; // Пустой вектор целых чисел
std::vector<int> vec2 = {1, 2, 3}; // Инициализация с помощью списка инициализации
Добавление элементов:
vec.push_back(10); // Добавляет элемент в конец вектора
vec.emplace_back(20); // Конструирует и добавляет элемент в конец (более эффективно)
Доступ к элементам:
int first = vec[0]; // Доступ без проверки границ
int second = vec.at(1); // Доступ с проверкой границ
Размер и емкость:
size_t size = vec.size(); // Текущее количество элементов
size_t capacity = vec.capacity(); // Количество элементов, для которых зарезервирована память
vec.reserve(100); // Резервирует память для 100 элементов
Итерация по элементам:
for (size_t i = 0; i < vec.size(); ++i) {
// Доступ по индексу
}
for (const auto& value : vec) {
// Диапазонный цикл для доступа к элементам
}
Вставка и удаление элементов:
vec.insert(vec.begin() + 1, 15); // Вставляет 15 на вторую позицию
vec.erase(vec.begin()); // Удаляет первый элемент
Очистка и проверка на пустоту:
vec.clear(); // Удаляет все элементы из вектора
bool isEmpty = vec.empty(); // Проверяет, пуст ли вектор
std::vector
является мощным и гибким контейнером, который упрощает работу с динамическими массивами, предоставляя множество методов для управления содержимым и оптимизации производительности.Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Если в C++ исключение не перехвачено ни одним блоком
catch
, вызывается функция std::terminate()
, которая по умолчанию завершает программу. Это может привести к неожиданной остановке работы приложения без корректного освобождения ресурсов или выполнения завершающих действий.Например:
#include <iostream>
void func() {
throw std::runtime_error("Ошибка"); // Выбрасывает исключение
}
int main() {
func(); // Вызов функции, которая выбрасывает исключение
std::cout << "Завершение программы" << std::endl;
return 0;
}
В этом коде функция
func()
генерирует исключение std::runtime_error
, но отсутствует блок try-catch
для его обработки. В результате программа вызывает std::terminate()
и аварийно завершается, не выводя "Завершение программы".Чтобы избежать этого, необходимо перехватить исключение:
int main() {
try {
func(); // Попытка вызвать функцию, которая может бросить исключение
} catch (const std::exception& e) {
std::cerr << "Перехвачено исключение: " << e.what() << std::endl;
}
std::cout << "Завершение программы" << std::endl;
return 0;
}
Теперь исключение перехватывается, выводится сообщение об ошибке, и программа корректно продолжает работу, выводя "Завершение программы".
Если исключение не перехвачено, это может привести к утечкам ресурсов, некорректному состоянию данных и затруднить отладку. Поэтому важно обеспечить соответствующую обработку возможных исключений в критических местах кода.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Паттерн "Абстрактная Фабрика" предоставляет интерфейс для создания семейств взаимосвязанных объектов без указания их конкретных классов. Это упрощает замену семейств продуктов и обеспечивает их совместимость.
Пример:
Абстрактные интерфейсы продуктов и фабрики:
// Абстрактный продукт
class Button {
public:
virtual void render() = 0;
};
// Абстрактная фабрика
class GUIFactory {
public:
virtual Button* createButton() = 0;
};
Конкретная реализация для Windows:
// Конкретный продукт для Windows
class WindowsButton : public Button {
public:
void render() override {
// Отображение кнопки в стиле Windows
}
};
// Конкретная фабрика для Windows
class WindowsFactory : public GUIFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
};
Использование фабрики:
int main() {
GUIFactory* factory = new WindowsFactory();
Button* btn = factory->createButton();
btn->render();
// Очистка ресурсов
delete btn;
delete factory;
return 0;
}
Паттерн "Абстрактная Фабрика" позволяет создавать объекты, не связываясь с конкретными классами, что облегчает поддержку и расширение кода.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
Принцип DRY (Don't Repeat Yourself) — один из ключевых принципов разработки программного обеспечения, который призывает избегать дублирования кода или логики. Каждый фрагмент знаний должен иметь единственное, непротиворечивое и авторитетное представление в системе.
Преимущества применения DRY:
- Снижение количества ошибок: Изменения в одном месте отражаются во всех частях системы, использующих этот код.
- Упрощение сопровождения: Легче обновлять и изменять код, когда логика сосредоточена в одном месте.
- Повышение читаемости: Код становится более чистым и понятным.
Пример нарушения DRY:
int calculateArea(int width, int height) {
return width * height;
}
int calculateRectangleArea(int width, int height) {
return width * height;
}
Здесь две функции выполняют одинаковые операции, что приводит к дублированию.
Применение принципа DRY:
int calculateArea(int width, int height) {
return width * height;
}
Теперь имеется одна функция для расчета площади, которую можно использовать во всех случаях, избегая повторений.
Принцип DRY способствует созданию более устойчивого и качественного кода, облегчая его развитие и поддержку в долгосрочной перспективе.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Управление временем выполнения программы в C++ включает измерение времени исполнения, оптимизацию кода и контроль длительности операций.
Измерение времени выполнения:
#include <chrono>
auto start = std::chrono::high_resolution_clock::now(); // Начало отсчёта
// Код для измерения времени выполнения
auto end = std::chrono::high_resolution_clock::now(); // Конец отсчёта
std::chrono::duration<double> duration = end - start; // Вычисление продолжительности
std::cout << "Время выполнения: " << duration.count() << " секунд\n";
Оптимизация кода:
- Эффективные алгоритмы и структуры данных: Использование подходящих алгоритмов снижает время выполнения.
- Профилирование: Инструменты, такие как gprof, помогают выявить узкие места.
- Оптимизации компилятора: Флаги
-O2
, -O3
для GCC улучшают производительность.Параллельное выполнение:
Использование потоков (std::thread) или асинхронных задач (std::async) для распараллеливания работы.
Установка таймаутов:
#include <future>
std::future<void> result = std::async(std::launch::async, []() {
// Длительная операция
});
if (result.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) {
// Обработка таймаута
}
Управление временем выполнения позволяет повысить эффективность программы и обеспечить своевременное выполнение задач.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
C++ является расширением языка C и предлагает дополнительные возможности, такие как поддержка объектно-ориентированного программирования (ООП), обобщенное программирование, стандартная библиотека шаблонов (STL) и другие современные особенности.
Основные отличия между C++ и C:
- Объектно-ориентированное программирование: C++ поддерживает классы, наследование, полиморфизм и инкапсуляцию, тогда как C не предоставляет этих возможностей.
- Шаблоны: C++ вводит шаблоны функций и классов для обобщенного программирования, что позволяет создавать универсальные и повторно используемые компоненты.
- Обработка исключений: В C++ имеется механизм обработки исключений (try, catch, throw), который отсутствует в C.
- Стандартная библиотека: C++ включает STL, предоставляющую контейнеры, алгоритмы и итераторы, упрощающие разработку.
- Пространства имен: C++ использует
namespace
для организации кода и предотвращения конфликтов имен.- Перегрузка функций и операторов: В C++ возможно создавать несколько функций с одинаковым именем, но разными параметрами, а также перегружать операторы для пользовательских типов.
Пример класса в C++:
class Point {
public:
Point(int x, int y) : x_(x), y_(y) {} // Конструктор
int getX() const { return x_; } // Получение координаты X
int getY() const { return y_; } // Получение координаты Y
private:
int x_;
int y_;
};
В C такой функционал необходимо реализовывать вручную, используя структуры и функции без поддержки ООП. C++ обеспечивает более высокий уровень абстракции и удобства для разработчиков, позволяя писать более чистый и модульный код.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В C++ существует несколько подходов к структурированию кода, которые помогают создавать поддерживаемые и масштабируемые приложения.
1. Процедурное программирование:
Основано на разделении программы на функции.
int add(int a, int b) {
return a + b; // Функция для сложения двух чисел
}
2. Объектно-ориентированное программирование (ООП):
Использует классы и объекты для моделирования сущностей и их взаимодействий.
class Animal {
public:
void speak() {
// Реализация метода speak
}
};
3. Шаблонное программирование:
Позволяет создавать обобщенный код с помощью шаблонов.
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b; // Функция для получения максимального значения
}
4. Модульность:
Разделение кода на файлы заголовков (.h) и реализации (.cpp) для улучшения организации.
5. Использование пространств имен:
Помогает избежать конфликтов имен и организовать код.
namespace Math {
int multiply(int a, int b) {
return a * b; // Функция умножения в пространстве имен Math
}
}
6. Функциональное программирование:
Использование ламбда-функций и стандартных алгоритмов.
#include <algorithm>
#include <vector>
std::vector<int> vec = {1, 2, 3, 4};
std::for_each(vec.begin(), vec.end(), [](int& n) {
n *= 2; // Удвоение каждого элемента
});
Комбинируя эти подходы, можно создавать эффективный и чистый код, облегчающий сопровождение и развитие проектов.
Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥1
std::deque
(double-ended queue) в C++ — это контейнер из стандартной библиотеки, который представляет собой двунаправленную очередь с возможностью эффективного добавления и удаления элементов.Основные особенности std::deque:
- Быстрый доступ к элементам: обеспечивает константное время доступа по индексу, аналогично
std::vector
.- Эффективное добавление и удаление: операции вставки и удаления в начало и конец выполняются быстро.
- Гибкость: подходит для случаев, когда требуется часто добавлять или удалять элементы.
Когда использовать std::deque:
- При необходимости частых операций вставки/удаления в начало и конец.
- Когда требуется быстрый доступ к элементам по индексу.
- Если нужно комбинировать преимущества
std::vector
и std::list
.Пример использования std::deque:
#include <deque>
#include <iostream>
int main() {
std::deque<int> dq;
dq.push_back(1); // Добавление в конец
dq.push_front(2); // Добавление в начало
dq[0] = 3; // Изменение элемента по индексу
// Итерация по элементам
for (const auto& elem : dq) {
std::cout << elem << " ";
}
// Вывод: 3 1
dq.pop_back(); // Удаление с конца
dq.pop_front(); // Удаление с начала
std::cout << "\nРазмер deque: " << dq.size(); // Вывод размера
return 0;
}
Основные методы std::deque:
-
push_back(value)
и push_front(value)
— добавление элементов в конец и начало.-
pop_back()
и pop_front()
— удаление элементов с конца и начала.-
operator[](index)
и at(index)
— доступ к элементу по индексу.-
size()
— получение количества элементов.-
empty()
— проверка на пустоту контейнера.-
clear()
— удаление всех элементов.std::deque
следует использовать, когда требуется эффективное добавление и удаление элементов вместе с быстрым доступом по индексу. Это делает его полезным в ситуациях, где нужны гибкость и производительность при работе с последовательностями данных.Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7