ЭКЗАМЕН ООП
.pdf
ЭКЗАМЕН ООП |
Блин ну у меня 4 автоматом получается, ради 12 баллов сижу |
|
это расписываю буэээээээээээээээээээээээээээээээээээээээээээ |
||
|
||
Typical IVT |
|
1 ООП, определение, основные принципы
ООП – парадигма программирования, в которой каждая программа рассматривается как набор взаимодействующих объектов. Каждый объект имеет аргументы и методы, которые работают с аргументами. Основные принципы ООП:
-Инкапсуляция Принцип объединения и сокрытия данных и методов объекта, т.е. внутренней реализации от внешнего мира.
Этот принцип необходим для защиты данных и упрощения взаимодействия с объектом.
-Наследование Механизм создание нового класса на основе существующего. Дочерний класс перенимает свойства и методы
родителя, а также может добавлять новые или переопределять унаследованные. Этот принцип позволяет избавиться от дублирования кода.
-Полиморфизм Способность объектов с одинаковым интерфейсом вести себя по разному в зависимости от их типа. Принцип
позволяет создавать единообразность, гибкость кода. Можно разделить на переопределение и перегрузку
-Абстракция Выделение значимых характеристик объекта и исключения незначительных.
2 Класс, объект, экземпляр класса, синтаксис класса в C++
Класс – тип данных, по сути шаблон, описывающий структуру и поведение будущих объектов. Объект или экземпляр класса – конкретная сущность в памяти, созданная по шаблону класса.
class class_name{ int arg;
int method(arg){};
}
Модификаторы доступа:
-private — члены доступны только внутри методов этого класса (по умолчанию для class).
-public — члены доступны отовсюду (интерфейс класса).
-protected — члены доступны внутри класса и его наследников.
3 Принцип инкапсуляции, сокрытие, уровни доступа в C++
Инкапсуляция – объединение данных и методов в единую сущность т.е. класс. Сокрытие данных – ограничение доступа к внутренним данным объекта или класса
|
Модификатор |
Доступ из того |
Доступ из |
Доступ из |
|
|
же класса |
производного класса |
внешнего кода |
|
|
|
|
|
|
private |
+ |
- |
- |
|
|
|
|
|
|
protected |
+ |
+ |
- |
|
|
|
|
|
|
public |
+ |
+ |
+ |
|
|
|
|
|
Для private пишут геттеры и сеттеры |
|
|
|
|
4 Конструкторы, деструкторы, специальные методы класса
В си существует целый ряд методов класса, которые автоматически генерируются компилятором или определяются программистом.
Конструктор – специальный метод, который автоматически вызывается при создании объекта.
-По умолчанию Может быть вызван без аргументов. Если в классе не объявлено ни одного конструктора, компилятор
сгенерирует его автоматически (неявный). Как только вы объявили любой другой конструктор, автогенерация подавляется.
-Параметризованный Принимает аргументы для инициализации
point(int x, int y) : _x(x), _y(y) {} // Инициализация через список
-Копирования Создает новый объект как копию существующего
ClassName(const ClassName& other);
-Перемещения Создает новый объект путем перемещения данных из другого (временного) объекта
электроника Стр.1
ClassName(ClassName&& other) noexcept;
Деструктор – специальный метод, вызываемый при уничтожении объекта. Не имеет аргументов и возвращаемого значения, освобождает память которую занимает объект.
~ClassName()
5 Принцип наследования, режим наследования, агрегация, композиция
Наследование – создание нового класса на основе существующего. Новый класс получает структуру и поведение родителя, может их дополнять и видоизменять. Это необходимо для избежания дублирования кода и реализации полиморфизма.
Режимы наследования определяют, как модификаторы доступа базового класса изменяются в дочернем.
Модификатор базового класса |
Public наследование |
Protected наследование |
Private наследование |
|
|
|
|
public |
public |
protected |
Private |
|
|
|
|
protected |
protected |
protected |
Private |
|
|
|
|
private |
private |
private |
private |
|
|
|
|
Агрегация – отношение между классами, при котором один класс содержит ссылку на другой в качестве своей части (в доме есть стул)
Композиция – принцип проектирования, при котором один класс содержит объекты других классов как свои атрибуты или компоненты. Объект-компонент не может существовать отдельно от объекта-контейнера (в доме есть комната)
Эти 2 принципа делают код более гибким и модульным. По-хорошему, лучше использовать их, а не наследование, если это возможно.
6 Множественное наследование, проблемы наследования, виртуальное наследование
Множественное наследование позволяет одному классу иметь более одного прямого родителя. class C : public A, public B {...}
Проблема инцеста ромба: класс наследуется от родителей, которые имеют общего предка. Дочерний класс будет содержать 2 экземпляра данных общего предка, а компилятор не сможет однозначно решить к кому из них обращаться.
Конфликты имен: у родителей могут быть одинаковые названия методов с разной логикой. Виртуальное наследование – механизм наследования, гарантирующий, что в производном классе будет
существовать единственны экземпляр общего предка, не зависимо от того, сколько раз он встречался до.
class PoweredDevice {int voltage = 220};
class Scanner : virtual public PoweredDevice { }; class Printer : virtual public PoweredDevice { }; class Copier : public Scanner, public Printer { };
Вместо того, чтобы содержать внутри себя непосредственный объект power device, классы сканер и принтер хранят на него указатель, и только copier имеет экземпляр power device.
7 Перегрузка функций, виртуальные функции, полиморфный класс
Перегрузка – создание нескольких функций с одинаковыми именами, но разными параметрами в одной области видимости. Это статический полиморфизм. Компилятор выберет нужную функцию на этапе компиляции на основе аргументов, переданных в функцию.
Виртуальная функция – метод, объявленный через virtual в базовом классе. Он предназначен для переопределения override в производных классах. Это динамический полиморфизм, нужная реализация выбирается на этапе выполнения (тут даже сигнатуры одинаковые).
Полиморфный класс — это класс, который содержит хотя бы одну виртуальную функцию. Объекты таких классов хранят внутри себя скрытый указатель на таблицу виртуальных функций vtable.
Vtable используется для реализации динамического полиморфизма. Это статический массив указателей на функции. Такая таблица создается для каждого полиморфного класса. В таблице хранится указатели на реализацию функций. Для каждого класса создается отдельная таблица, в которой будут и базовые и переопределенные методы. Чтобы объект знал какую таблицу использовать, компилятор добавляет в экземпляр класса vptr.
8 Чистые виртуальные функции, абстрактный класс
Чистая виртуальная функция не имеет реализации в базовом классе и объявляется через = 0. Так, подразумевается, что любой, кто наследуется от этого класса, должен иметь свою реализацию этой функции.
Абстрактный класс содержит хотя бы одну чистую виртуальную функцию. Нельзя создать объект абстрактного класса. Производный класс становится конкретны ↔ переопределяются все чистые виртуальные функции.
9 Обработка исключений, достоинства и недостатки, класс std::exception
Обработка исключений предназначена для реагирования на ошибки. Реализуются через try, catch, throw. Если
электроника Стр.2
исключение не будет поймано, программа аварийно завершится.
int main() { try {
double result = divide(10.0, 0.0);
std::cout << "Результат: " << result << std::endl;
}
catch (const std::runtime_error& e) {
// Обработка конкретного типа исключения
std::cerr << "Ошибка времени выполнения: " << e.what() << std::endl;
}
catch (const std::exception& e) {
// Обработка любого стандартного исключения
std::cerr << "Стандартное исключение: " << e.what() << std::endl;
}
catch (...) {
// Обработчик ВСЕХ исключений (любого типа) std::cerr << "Неизвестное исключение" << std::endl;
}
return 0;
}
В блоке try может возникнуть ошибка. Catch проверяют сверху вниз наличие ошибки. Throw создает объект исключения и запускает процесс раскрутки стека.
Достоинства:
-Разделение кода
-Гарантированная реакция
-Раскрутка стека (т.е. ошибка может быть обработана там, где это имеет смысл)
-Можно создавать свои типы ошибок Недостатки:
-Сложность реализации, т.к. компиляторы генерируют дополнительный код для обработки исключений, что увеличивает размер программы и может замедлить выполнение.
-Trow это, по сути, goto в неизвестное место. Иногда сложно понять куда ушел объект.
Все стандартные исключения наследуются от класса std::exception из <exception>. Их там довольно много, но из основных: invalid_argument, out_of_range, run_time_error, overflow_error, system_error.
Чтобы создать свой собственный класс исключений, можно унаследовать его от стандартных исключений.
Есть ключевое слово noexcept (c++11). Если из функции с этим ключем вылетает исключение программа вызовет std::terminate. Ими принято помечать деструкторы.
10 Раскручивание стека при обработке исключений
Раскручивание стека – это процесс, при котором при возникновении исключения среда выполнения последовательно «проходится» вверх по стеку вызовов, завершая функции и уничтожая локальные объекты, пока не будет найден обработчик исключения соответствующего типа.
Когда в программе генерируется исключения, начинается поиск подходящего catch. Среда выполнения последовательно проверяет каждый фрейм стека, для каждого проверяется наличие блока try с соответствующий обработчиком. Для каждого прекратившего существование фрейма вызываются деструкторы всех локальных объектов с автоматическим временем хранения. Когда находится подходящий catch, начинается его выполнение. Если исключение не перехвачено вызывается std::terminate.
11 Идиома RAII; языки программирования с автоматической сборкой мусора
RAII resource acquisition is initialization – идиома, при которой ресурс (память, файл и т.п.) захватывается в конструкторе объекта и гарантированно освобождается в деструкторе, т.е. владение ресурсом привязано к времени жизни объекта на стеке.
Достоинства RAII:
-Детерминированность, т.е. ресурсы освобождаются как только объект выходит из области видимости.
-RAII и раскрутка стека лучшие подружки
-Не надо лишний раз самостоятельно ничего чистить ура
Языки с автоматической сборкой мусора отличаются тем, что за управление памятью ответственна среда выполнения, а не программист. Специальный сборщик мусора определяет, какие объекты больше не достижимы и чистит память.
К таким языкам относятся Java, Python, Go, Ruby.
Однако, сборка мусора занимается исключительно памятью. В таких языках для управления файлами, сокетами и
электроника Стр.3
прочим тоже применяется RAII.
12 Перегрузка операторов, типы операторов, правила перегрузки
Перегрузка операторов – это механизм C++, позволяющий переопределить поведение стандартных операторов (+, -, =, << и т.д.) для пользовательских типов.
Типы операторов:
-По количеству операндов: унарные, бинарные, тернарные
-По функциональности: арифметические, сравнительные, логические, побитовые, операторы доступа
-Специальные: получение адреса &, оператор разыменования *, sizeof(), область видимости ::
По способу перезагрузки операторы бывают:
-Функция-член класса. Оператор определяется внутри класса, т.е. первым операндом является объект класса
(*this)
class Vector2D { public:
int x, y;
Vector2D(int x, int y) : x(x), y(y) {}
// Перегрузка сложения как метод
Vector2D operator+(const Vector2D& rhs) const { return Vector2D(x + rhs.x, y + rhs.y);
}
};
-Дружественная функция. Оператор определятся как отдельная функция и для доступа к аргументам объявляется как friend
class Vector2D {
int x, y; // private public:
Vector2D(int x, int y) : x(x), y(y) {}
// friend-функция для доступа к x и y
friend Vector2D operator+(const Vector2D& lhs, const Vector2D& rhs);
};
Vector2D operator+(const Vector2D& lhs, const Vector2D& rhs) { return Vector2D(lhs.x + rhs.x, lhs.y + rhs.y);
}
Нельзя перегружать операторы для встроенных типов. Нельзя создать новый оператор. Нельзя изменить количество операндов. Нельзя изменить приоритет выполнения и правило ассоциативности.
13 Шаблонные функции, достоинства и недостатки шаблонов
Шаблоны позволяют писать код, независящий от конкретных типов данных.
Шаблонная функция описывает семейство функций которые отличаются только типами аргументов. Конкретная функция создается компилятором при вызове.
template <typename T> // T — параметр шаблона T max(T a, T b) {
return (a > b) ? a : b;
}
Достоинства:
-Нет дублирования кода
-Ошибки ловятся на этапе компиляции
-Статический полиморфизм Недостатки:
-Для каждой уникальной функции генерируется отдельный экземпляр
-Увеличение времени компиляции
-Реализация должна быть в заголовочном файле
-Сложно отлаживать
14 Шаблонные классы, специализация шаблона
Шаблонный класс делается на template (duh). Компилятор генерирует конкретный класс, когда создается экземпляр с конкретным типом.
template <typename T> class Box {
T content;
электроника Стр.4
public:
Box() = default;
explicit Box(const T& val) : content(val) {}
const T& get() const { return content; } void set(const T& val) { content = val; }
Определение шаблонного класса должно быть видимо в каждой единице трансляции. Короче, надо все писать в заголовочном файле.
Специализация шаблона позволяет определить особую реализацию для конкретного набора параметров. Компилятор сам выбирает более специализированную версию.
//Основной шаблон template <typename T> class Storage {
T data; public:
void info() { std::cout << "Общее хранилище\n"; }
};
//Полная специализация для bool
template <>
class Storage<bool> { bool data;
public:
void info() { std::cout << "Специализированное хранилище для bool\n"; }
};
Полная специализация определяет версию для одного конкретного типа или набора параметров. Такая специализация по сути, уже не шаблон и ее реализацию можно выносить в cpp.
Частичная специализация применяется только для шаблонных классов. Фиксируется часть параметров
template <typename T> class Pair<T, int> { public:
void info() { std::cout << "Специализация Pair<T, int>\n"; }
};
15 Обобщенное программирование, методы обобщенного программирования
Обобщенное программирование – парадигма, в которой алгоритмы и структуры пишутся таким образом, чтобы их можно было использовать с разными типами, не переписывая код. Обобщенное программирование фокусируется на статическом полиморфизме.
Методы обобщенного программирования:
-Шаблоны
-Концепции – набор требований к типам (например, какие операции тип должен поддерживать)
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>; // Требует оператор +, возвращающий T
};
-Итераторы. Итераторы это абстракции, которые предоставляют унифицированный способ доступа к элементам контейнера, не зависящий от внутренней структуры контейнера. Они позволяет алгоритмам типа std::sort и т.п. работать и с массивами и с векторами и т.д. Например, begin() — возвращает итератор на первый элемент контейнера.
16 Статические поля и методы класса, константные методы, дружественные функции
Статические члены класса принадлежат самому классу, а не отдельным объектам. Они существуют в единственном экземпляре для всего класса.
Статические поля объявляются словом static и хранят данные общие для всех объектов класса, типа счетчика объектов класса. Память под поле выделяется один раз при инициализации, а делать это нужно вне объявления, иначе возникнет ошибка множественного определения.
Статические методы можно вызвать как через имя класса, так и через объект класса. Им не передается указатель *this, и обращаться они могут только к статическим полям и вызывать другие статические методы.
Константные методы помечаются const после списка параметром и гарантирует, что он не будет изменять члены класса. Константные методы могут вызывать только другие константные методы.
Дружественные функции не являются членами класса, но получают доступ к private и protected членам. Для их
электроника Стр.5
объявления используют слово friend. Дружественной функцией может быть глобальная функция или функция, определенная ранее в другом классе. Ей не передается указатель this, объекты необходимо передавать явно. На дружественную функцию не распространяются спецификаторы доступа. Дружественной функция может быть сразу для нескольких классов. Вообще, можно сделать дружественным весь другой класс.
17 Типы данных C++, enum, namespace, ссылки и указатели, константные ссылки
Фундаментальные (встроенные) типы:
-Целочисленные: int, short, long, long long (и их unsigned версии), char, bool.
-С плавающей точкой: float, double, long double.
-Пустой тип: void.
-std::nullptr_t: тип литерала nullptr.
Составные типы:
-Указатели: int*, void*.
-Ссылки: int&, const double&.
-Массивы: int arr[10].
-Функции. Пользовательские типы:
-Перечисления: enum, enum class.
-Классы и структуры: class, struct.
-Объединения: union
Перечисления enum – это пользовательский тип данных, который представляет собой набор именованных целочисленных констант. Они позволяют присвоить осмысленные имена значениям, что улучшает читаемость кода. Лучше задавать через класс, в силу большей безопасности типов.
enum class Color { Red, Green, Blue };
Color c = Color::Red; // Обязательно указывать область видимости int x = static_cast<int>(Color::Red); // Явное преобразование
Пространство имен namespace – механизм для группировки именованных сущностей (переменных, функций, классов и т.д.) под одним именем. Позволяет организовать код в логические группы, избежать конфликтов имен, особенно в крупных проектах или при использовании библиотек. Внутри пространства имен к его компонентам можно обращаться без указания имени пространства, а извне необходимо использовать полное имя и оператор видимости ::
Директива using позволяет использовать все или некоторые сущности из пространства без указания имени, но так лучше не делать.
Пример пространства имен: std
Ссылка – это псевдоним для уже существующего объекта в памяти. Если изменить ссылку, изменится и исходный объект.
int x = 42;
int& ref = x; // ref — это псевдоним для x
Нельзя объявить ссылку без привязки к объекту, переназначить после инициализации. Удобно применять когда нужно передавать в функцию большие объекты типа строк, векторов, классов. Обычно используют константные ссылки, чтобы гарантировать, что функция не изменит переданный объект. Они позволяют только читать данные из переменной, но не изменять их.
Указатель – переменная, которая хранит адрес другой переменной в памяти. Он не владеет значением.
int x = 42;
int* ptr = &x; // ptr хранит адрес переменной x
Указатель можно переназначить, его можно сделать пустым, поддерживает арифметику, и требует явного разыменования.
18 Умные указатели C++
Умные указатели это специальные RAII обертки над обычными указателями, которые автоматически управляют временем жизни в выделенной памяти. В общем, позволяют практически полностью отказаться от ручного new и delete. Это позволяет избежать утечек памяти и висячих указателей.
Умный указатель работает как обычный, но когда он выходит за область видимости, его деструктор автоматически освобождает ресурс.
Вси++ они определены в заголовке <memory>, и бывают нескольких видов:
-std::unique_ptr – обеспечивает уникальное владение. Нельзя копировать, но можно перемещать (передавать владение в другой объект). Подходит, когда у ресурса есть ровно один владелец.
электроника Стр.6
-std::shared_ptr – реализует разделяемое владение с подсчётом ссылок. Несколько shared_ptr могут владеть одним ресурсом. Счётчик увеличивается при копировании указателя и уменьшается в деструкторе. Ресурс удаляется, когда счётчик достигает нуля
-std::weak_ptr – не владеет объектом. Он содержит «слабую» ссылку на объект, которым управляет shared_ptr. Его задача разорвать циклические зависимости (когда объекты ссылаются друг на друга), предотвращая утечку памяти.
19 Лямбда-функции, синтаксис в C++
Лямбда-функция – удобный способ записать анонимную функцию прямо в том месте, где она нужна. Лямбда с параметрами:
auto add =(int a, int b) { return a + b; }; std::cout << "Sum: " << add(5, 3) << std::endl;
Лямбда с захватом переменных:
int x = 10, y = 20;
auto add = [x, y]() { return x + y; }; // Захват по значению std::cout << "Sum: " << add() << std::endl;
// Можно захватить и по ссылке: [&x, &y] auto add_ref = [&x, y]() { return x + y; };
std::cout << "Sum: " << add_ref() << std::endl;
О способах захвата
[] |
Ничего не захватывается |
|
|
[=] |
Захват всех используемых переменных по значению (копии) |
|
|
[&] |
Захват всех используемых переменных по ссылке |
|
|
[x, &y] |
x — по значению, y — по ссылке (остальные недоступны) |
|
|
[=, &z] |
Всё по значению, но z — по ссылке |
|
|
[&, z] |
Всё по ссылке, но z — по значению |
|
|
[this] |
Захват указателя this (доступ к членам класса) |
|
|
[*this] |
Захват копии объекта *this |
|
|
Обычно, компилятор автоматически подбирает возвращаемый тип, но если нужно казать явно: auto divide = [](double x, double y) -> double {...}
По умолчанию лямбда, захватившая переменные по значению, не может их изменять. Ключевое слово mutable снимает это ограничение.
20 Коллекции данных, std::vector
Под коллекциями данных подразумеваются контейнеры – структуры стандартной библиотеки, которые служат для хранения набора элементов определенного типа и предоставляют механизмы работы с ними.
Контейнеры бывают:
-Последовательные. Элементы в них хранятся последовательно и порядок определяется моментом вставки.
Array, vector, list
-Ассоциативные. В них с каждым элементом связан ключ, по которому можно получить их значение. Set, map.
-Контейнеры-адаптеры. Они не поддерживают работу итераторов, предоставляют ограниченный интерфейс.
Stack, queue.
Итераторы позволяют последовательно перебирать все элементы контейнера и обеспечивают единый интерфейс для разных типов.
Std::vector – последовательный контейнер, реализующий динамический массив. Вектор сам выделяет и освобождает память под элементы. Сам по себе вектор это шаблон и его нужно типизировать.
#include <vector>
std::vector<int> numbers; // пустой вектор
std::vector<int> numbers2(5); // вектор из 5 элементов, каждый по умолчанию (0) std::vector<int> numbers3(5, 2); // вектор из 5 элементов, каждый равен 2 std::vector<int> numbers4 = {1, 2, 3, 4, 5}; // инициализация списком
Size() – количество элементов, которое хранится в массиве Capacity() – количество элементов под которое выделена память. Puch_back(), pop_back() добавляют и удаляют элемент в конце.
Вектор лучше использовать когда нужно постоянно добавлять элементы в конец массива и не обращаться к началу или середине.
электроника Стр.7
21 Коллекции данных, std::list
Лист реализует двусвязный список (орспо все учили да). Сам контейнер держит указатели на первый и последний узлы.
Доступа по индексам нет. Вставка и удаление происходят за О(1) если есть итератор на позицию. При удалении других элементов, итераторы и ссылки на остальные элементы остаются действительными.
Merge(), remove() специально оптимизированы под листы.
Т.к. указатель указывают на соседние узлы он занимает больше памяти.
Если нужно вставлять и удалять из середины, перестраивать список – лист хорошо подходит.
#include <list>
std::list<int> lst = {1, 2, 3};
20 Коллекции данных, std::map
Мап – ассоциативный контейнер, который хранит пары ключ-значение, при том автоматически сортирует их по ключам. По сути, это красно-черное дерево, так что вставка, поиск и т.п. реализуется за O(log n).
Все ключи уникальны. При объявлении указывается тип ключа и тип значения.
#include <iostream> #include <map> #include <string>
std::map<std::string, int> scores; scores["Alice"] = 90; scores["Bob"] = 75;
std::cout << scores["Alice"] << std::endl;
Если обратиться через [] к ключу, которого нет, контейнер автоматически создаст такой ключ с значением по умолчанию, чтобы этого избежать можно использовать find().
Чтобы использовать мап с пользовательским типом данных нужно перегрузить оператор < для корректной сортировки.
Есть также std::unordered_map, он не учитывает порядок элементов, но при том работает быстрее.
23 Итераторы в C++, типы итераторов
Итераторы, по сути дела, это обобщенные указатели, предоставляющие единый способ доступа к элементам контейнера, независимо от его типа. Итераторы позволяют написать 1 алгоритм и применять его к разным контейнерам.
Базовые операции с итераторами:
-begin() — итератор на первый элемент.
-end() — итератор на позицию за последним элементом (past-the-end).
-++it — переход к следующему элементу.
-*it — разыменование (доступ к элементу, на который указывает итератор).
-it->member — доступ к члену элемента (аналог (*it).member).
Тип итератора |
Операции |
Примеры контейнеров |
|
|
|
Input |
++, * (чтение), ==, != |
Поток ввода (std::istream_iterator) |
|
|
|
Output |
++, * (запись) |
Поток вывода |
|
|
(std::ostream_iterator) |
|
|
|
Forward (Однонаправленный) |
Всё от Input + многопроходность, |
std::forward_list |
|
копирование |
|
|
|
|
Bidirectional (Двунаправленный) |
Всё от Forward + -- |
std::list, std::set, std::map |
|
|
|
Random Access |
Всё от Bidirectional + +, -, [], <, >, +=, -= |
std::vector, std::deque, std::array, |
(Произвольного доступа) |
|
сырой массив |
|
|
|
Contiguous (Непрерывный, C++17) |
Всё от Random Access + гарантированно |
std::vector, std::array |
|
непрерывная память |
|
|
|
|
Каждый последующий типа включает в себя возможности предыдущего.
24 Библиотека алгоритмов std: copy, sort, find, find_if
Алгоритмы работают через итераторы, что делает их универсальными.
std::copy копирует элементы из диапазона[first, las) в диапазон, начинающийся с итератора.
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> dest(5); // Приёмник должен иметь достаточно места std::copy(source.begin(), source.end(), dest.begin());
электроника Стр.8
Новый диапазон должен иметь достаточно места. Если новый диапазон находится внутри изначального, ждите неопределенного поведения.
std::sort сортирует элементы из диапазона в порядке возрастания (по умолчанию через оператор <)
std::vector<int> numbers = {5, 2, 8, 1, 9};
std::sort(numbers.begin(), numbers.end()); // сортировка по возрастанию
Сорт работает только с операторами произвольного доступа (с индексацией), например с list работать не будет.
std::find ищет первое вхождение элемента по заданному значению, возвращает итератор на него.
std::vector<int> nums = {1, 2, 3, 4, 5};
auto it = std::find(nums.begin(), nums.end(), 3);
std::find_if ищет первый элемент для которого предикат возвращает true.
std::vector<int> numbers = {10, 20, 30, 25, 40};
auto it = std::find_if(numbers.begin(), numbers.end(),(int n) { return n % 2 != 0; });
Он вызывает предикат для каждого элемента, если предикат вернул true, алгоритм возвращает итератор на этот элемент. Если для всех элементов предикат выдал false, алгоритм вернет last.
электроника Стр.9
