init commit
This commit is contained in:
+221
@@ -0,0 +1,221 @@
|
||||
## Мини-отступление
|
||||
|
||||
```cpp
|
||||
#include <utility>
|
||||
C f() {
|
||||
C local var;
|
||||
|
||||
// return local_var - криво
|
||||
return std::move(local_var)
|
||||
}
|
||||
```
|
||||
|
||||
Благодаря std::move можно не создавать вторую переменную для возвращаемого значения. Входит в стандарт с c++17 и оптимизируется автоматически в c++14.
|
||||
|
||||
---
|
||||
|
||||
# Перегрузка операций
|
||||
|
||||
## Дружеские функции
|
||||
|
||||
```cpp
|
||||
class C {
|
||||
int a;
|
||||
public:
|
||||
...
|
||||
friend void f(C &x);
|
||||
};
|
||||
|
||||
void f(C &x) {cout << x.a}
|
||||
```
|
||||
|
||||
функция также может относиться к другому классу
|
||||
|
||||
## Перегргузка операций
|
||||
|
||||
Нельзя перегружать:
|
||||
|
||||
- \#
|
||||
- ::
|
||||
- ?:
|
||||
- .
|
||||
- .\*
|
||||
- sizeof
|
||||
- typeid
|
||||
|
||||
### Бинарные операции
|
||||
|
||||
```cpp
|
||||
class C{
|
||||
double re;
|
||||
double im;
|
||||
public:
|
||||
C (double x = 0.0, double y = 0.0) : re(x), im(y) {}
|
||||
bool isEqual(C &obj) {
|
||||
return re == obj.re && im == obj.im; // неявная подстановка this->
|
||||
}
|
||||
|
||||
bool operator ==(C &obj) {
|
||||
return re == obj.re && im == obj.im;
|
||||
}
|
||||
|
||||
// нужен const, чтобы можно было делать o3 = o1 + 10.0
|
||||
C operator+(const C& obj) {
|
||||
return C(re + obj.re, im + obj.im);
|
||||
} // o3 = o1 + o2
|
||||
};
|
||||
|
||||
void main() {
|
||||
C o1, o2, o3;
|
||||
|
||||
o1.isEqual(o2) == (o1 == o2); // the same
|
||||
|
||||
o3 = o1 + o2;
|
||||
o3 = o1 + 10.0
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
либо для дальнейшей работы и `o1 = 10.0 + o2` изменим перегрузку операнда:
|
||||
|
||||
```cpp
|
||||
friend C operator+(const C& obj1, const C& obj2) {
|
||||
return C(obj2.re + obj1.re, obj2.im + obj1.im);
|
||||
}
|
||||
```
|
||||
|
||||
### Унарные операции
|
||||
|
||||
```cpp
|
||||
C operator-() {
|
||||
return C(-re, -im);
|
||||
} // o3 = -o1
|
||||
// !! не перегрузит никак бинарную
|
||||
|
||||
```
|
||||
|
||||
Посткремент и инкремент:
|
||||
|
||||
```cpp
|
||||
C& operator++() {
|
||||
re++;
|
||||
im++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
C operator++(int NU) { // not used var
|
||||
С tmp(re, im);
|
||||
re++;
|
||||
im++;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void main() {
|
||||
o3 = ++o1;
|
||||
o3 = o1++;
|
||||
}
|
||||
```
|
||||
|
||||
`o3 = (o1++)++;` не проработает!! (изменит временную переменную)
|
||||
|
||||
### Перегрузка =, [], ()
|
||||
|
||||
> не перегружаются как дружественные!
|
||||
|
||||
```cpp
|
||||
C &operator=(const C &obj) {
|
||||
re = obj.re;
|
||||
im = obj.im;
|
||||
|
||||
return *this;
|
||||
} // по умолчанию так перегружается
|
||||
```
|
||||
|
||||
## Итоговый пример
|
||||
|
||||
```cpp
|
||||
int
|
||||
main() {
|
||||
string s1("abcd"), s2("qw"), s3;
|
||||
s2[1] = 'A';
|
||||
s2.print();
|
||||
s3 = s1 + s2;
|
||||
|
||||
s3.print();
|
||||
}
|
||||
```
|
||||
|
||||
Итоговый код, чтобы условие выше выполнялось:
|
||||
|
||||
```cpp
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
class string
|
||||
{
|
||||
int len; // количество памяти
|
||||
char* str;
|
||||
|
||||
public:
|
||||
string(const char* s = "") {
|
||||
len = strlen(s) + 1;
|
||||
str = new char[len];
|
||||
strcpy(str, s);
|
||||
}
|
||||
|
||||
char&
|
||||
operator[](int n) {
|
||||
return str[n];
|
||||
}
|
||||
|
||||
string
|
||||
operator+(string s) {
|
||||
string tmp;
|
||||
tmp.len = s.len + len - 1;
|
||||
tmp.str = new char[tmp.len];
|
||||
|
||||
strcpy(tmp.str, str);
|
||||
strcpy(tmp.str + len - 1, s.str);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string
|
||||
operator=(string s) {
|
||||
if (s.str == str) {
|
||||
return s;
|
||||
}
|
||||
|
||||
delete[] str;
|
||||
len = s.len;
|
||||
str = new char[len];
|
||||
strcpy(str, s.str);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ~string() { delete[] str; } почему-то с ним не работает (?)
|
||||
|
||||
void
|
||||
print() {
|
||||
std::cout << str << " " << len << std::endl;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
версия присваивания получше:
|
||||
|
||||
```cpp
|
||||
void string::swap(string& a) {
|
||||
std::swap(str, a.str);
|
||||
std::swap(len, a.len);
|
||||
}
|
||||
|
||||
string& string::operator=(string a) {
|
||||
swap(a);
|
||||
|
||||
return *this;
|
||||
}
|
||||
```
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
#
|
||||
|
||||
## Про оптимизации
|
||||
|
||||
```cpp
|
||||
A obj = A(10); // A(const A&)
|
||||
obj1 = obj; // A(A&)
|
||||
```
|
||||
|
||||
при отключении оптимизации будет:
|
||||
|
||||
- преобразования
|
||||
- копирования
|
||||
- деструктор
|
||||
|
||||
На экзе во всех задачах _вероятно_ отключена оптимизация
|
||||
|
||||
```cpp
|
||||
A f(...) {
|
||||
A local;
|
||||
return local;
|
||||
}
|
||||
```
|
||||
|
||||
будет создаваться 2 переменные.
|
||||
|
||||
## Перегрузка (продолжение)
|
||||
|
||||
### Приведение типов
|
||||
|
||||
```cpp
|
||||
operator double() {
|
||||
return re;
|
||||
}
|
||||
double x = 3.1, y;
|
||||
y = C1 + x; // !error - не понятно, к какому типу
|
||||
y = double(C1) + x == C1 + C(x);
|
||||
```
|
||||
|
||||
### Ввод/вывод
|
||||
|
||||
```cpp
|
||||
friend ostream & operator<<(ostream &os, C&a) {
|
||||
os << "re=" << a.re << ...;
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
C obj(1,2);
|
||||
cout << obj; // ostream and class
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Перегрузка вызова функции
|
||||
|
||||
```cpp
|
||||
struct Pred {
|
||||
bool operator()(int v) {
|
||||
return v < 10;
|
||||
}
|
||||
};
|
||||
|
||||
void f(int *mas, int n, Pred(c)) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (c(mas[i])) {
|
||||
mas[i] *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Перегрузка функций
|
||||
|
||||
Алгоритм для поиска наиболее подходящей функции для вызова
|
||||
|
||||
1. по количеству параметров
|
||||
2. отбросить недопустимые преобразования
|
||||
3. точные совпадения (на typedef):
|
||||
1. T <-> T&
|
||||
2. T[] <-> \*T
|
||||
3. T -> const T
|
||||
4. можно расширить тип (например к инт):
|
||||
1. unsigned char
|
||||
2. unsigned short
|
||||
3. short and etc
|
||||
4. float -> double (нет лонг дабл)
|
||||
5. стандартные преобразования
|
||||
- Любой числовой приводится к любому числовому типу
|
||||
- Любой указатель приводится к указателю на void
|
||||
- 0 к любому указателю или любому числовому
|
||||
6. пользовательсткие преобразования
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
const int ci = 1;
|
||||
void f(int y) {...}
|
||||
|
||||
f(ci); // всё ок
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
алгоритм (фактически):
|
||||
|
||||
- отбрасываем неподходящие
|
||||
- по каждому параметру берём множество подходящих функций
|
||||
- смотрим персечение
|
||||
|
||||
```cpp
|
||||
struct A {
|
||||
operator int() { return 1; }
|
||||
void f(double d, char c); // 1
|
||||
void f(double d, int j); // 2
|
||||
void f(A a, const char *p); // 3
|
||||
void f(int i, const char *p); // 4
|
||||
};
|
||||
|
||||
int main() {
|
||||
A a;
|
||||
|
||||
f(a, 0); // 3 & 2 => 0
|
||||
f(a, 'a'); // 12 & 1 => 1
|
||||
f('a', 0); // 4 & 2 => 0
|
||||
}
|
||||
```
|
||||
|
||||
## Статические члены класса
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
int a;
|
||||
static int b;
|
||||
public:
|
||||
A(int x) : a(x) { }
|
||||
static void f() {
|
||||
cout << b;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
int A::b = 77;
|
||||
A::f();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
требования:
|
||||
|
||||
- работа только с статик полями
|
||||
- вызывать только статик функции
|
||||
- нельзя как const или virtual объявить (void f const { } // может менять статик и mutable поля)
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
static int x;
|
||||
int y;
|
||||
public:
|
||||
int f(int x) const {};
|
||||
};
|
||||
|
||||
int main() {
|
||||
const A a;
|
||||
a.x = 3;
|
||||
cout << a.y << a.x << a.f(1);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
struct A {
|
||||
int n;
|
||||
int k;
|
||||
A (A &a) { n = a.n; }
|
||||
int f() { return k; }
|
||||
A (int a) { n = a; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
A a = A(1), b;
|
||||
cout << A::f() << " " << a.k << a.n << endl; // 5 53
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
struct A {
|
||||
int n;
|
||||
static int k;
|
||||
A (const A &a) { n = a.n; }
|
||||
static int f() { return k; }
|
||||
A (int a = 3) { n = a; }
|
||||
};
|
||||
|
||||
int A::k = 5;
|
||||
|
||||
int main() {
|
||||
A a = A(1), b;
|
||||
cout << A::f() << " " << a.k << b.n << endl; // 5 53
|
||||
}
|
||||
```
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
# Третий семинар
|
||||
|
||||
## Шаблоны
|
||||
|
||||
```cpp
|
||||
// template <typename>
|
||||
template <class T>
|
||||
void swap(T& a, T& b) {
|
||||
T tmp;
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
```
|
||||
|
||||
Можно применять и от нескольких неизвестных параметров
|
||||
|
||||
```cpp
|
||||
template <typename T, typename K>
|
||||
void transfer(T fromAccount, T toAccount, K code, int sum)
|
||||
{
|
||||
std::cout << "From: " << fromAccount << "\nTo: " << toAccount
|
||||
<< "\nSum: " << sum << "\nCode: " << code << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
Пример кода для абсолютного значения:
|
||||
|
||||
```cpp
|
||||
template <class T> T abs(const T& x) {
|
||||
// template <class T> T abs(T x) {
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
```
|
||||
|
||||
Суммирование элементов массива
|
||||
|
||||
```cpp
|
||||
template <class T> T sum(T* mas, int N) {
|
||||
T res = 0;
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
res += mas[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int main() {
|
||||
double mas[5] = {...};
|
||||
std::cout << sum(mas, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
template <class T> T sum(T* mas, int N) {
|
||||
T res = 0;
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
res += mas[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
double mas[5] = {...};
|
||||
std::cout << sum<double, 5>(mas);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Что-то про стэк
|
||||
|
||||
Вторая задача:
|
||||
Суть была реализовывать динамически расширяемый массив
|
||||
|
||||
```cpp
|
||||
template<class T, int SIZE>
|
||||
class st {
|
||||
T st[SIZE];
|
||||
int top = 0;
|
||||
public:
|
||||
void push(T a) {
|
||||
if (top == SIZE) {
|
||||
// error
|
||||
} else {
|
||||
st[top++] = a;
|
||||
}
|
||||
}
|
||||
T pop();
|
||||
}
|
||||
|
||||
template<class T, int SIZE>
|
||||
T st<T, SIZE>::pop() {
|
||||
|
||||
return st[--top];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Если указать стандартное значение для каких-то параметров, вызов обычный
|
||||
|
||||
## Библиотеки
|
||||
|
||||
### Контейнеры
|
||||
|
||||
#### Последовательности
|
||||
|
||||
- list - двунаправленный список
|
||||
- vector
|
||||
- deque - очередь
|
||||
|
||||
На их основе создаются:
|
||||
|
||||
- stack
|
||||
- queue
|
||||
|
||||
#### Ассоциативные массивы
|
||||
|
||||
- map - отображения
|
||||
- multimap - ключ может несколько раз встречаться
|
||||
- set - уникальные упорядоченные ключи
|
||||
- multiset - совпадающие ключи
|
||||
|
||||
### Итераторы
|
||||
|
||||
`#include <algorithm>` - подключение библиотеки
|
||||
|
||||
- value_type - тип значений в контейнере
|
||||
- size_type - аналог size_t
|
||||
- reference/ const reference - ссылки на элемент
|
||||
- pointer/const pointer - указатели
|
||||
|
||||
Исполняют роль указателей
|
||||
|
||||
Для каждого контейнера определён:
|
||||
|
||||
- iterator - идёт от начала
|
||||
- reverse_iterator - идёт с конца
|
||||
- const_iterator - не меняет значений
|
||||
- const_reverse_iterator - не меняет значений, ревёрс
|
||||
|
||||
```cpp
|
||||
begin(), end();
|
||||
rbegin(), rend();
|
||||
|
||||
cbegin(), cend(); // для константных
|
||||
```
|
||||
|
||||
Виды итераторов:
|
||||
|
||||
- input
|
||||
- output
|
||||
- forward
|
||||
- bidirectional - list, map, set
|
||||
- random_access - для vector deque, можно индексировать, += n
|
||||
|
||||
```cpp
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
vector<int> v1; // длина 0
|
||||
vector<int> v2(5); // длина 5, занулены
|
||||
vector<int> v3(10, '*');
|
||||
int m[] = {1, 2, 3, 4};
|
||||
vector<int> v4(m, m + 4);
|
||||
// vector<int> v4(m.begin(), m.end());
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
for (int i = 0; i < v.size(); ++i)
|
||||
cout << v[i] << " "; // только для random_access контейнера
|
||||
|
||||
v[i] == v.at(i) // выдаёт out_of_range, если нет элемента
|
||||
```
|
||||
|
||||
Печать элементов в прямом и обратном при помощи итераторов
|
||||
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
// прямой с помощью прямого
|
||||
void f1(std::vector<int> mas) {
|
||||
std::vector<int>::std::iterator iter = mas.begin();
|
||||
while (iter != mas.end()) {
|
||||
std::cout << *iter << " ";
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// обратный с помощью реверсивного
|
||||
void f2(std::vector<int> mas) {
|
||||
std::vector<int>::std::reverse_iterator iter = mas.rbegin();
|
||||
while (iter != mas.rend()) {
|
||||
std::cout << *iter << " ";
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// обратный с помощью прямого
|
||||
void f3(std::vector<int> mas) {
|
||||
std::vector<int>::std::iterator iter = mas.end();
|
||||
while (iter != mas.begin()) {
|
||||
--iter;
|
||||
std::cout << *iter << " ";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Или же код нормального человека:
|
||||
|
||||
```cpp
|
||||
for (auto x : v) cout << x << " ";
|
||||
```
|
||||
|
||||
### Алгоритмы
|
||||
|
||||
Некоторые методы контейнеров:
|
||||
|
||||
- `size_type size()` - количество элементов в контейнере
|
||||
- `bool empty()` - пустой ли контейнер
|
||||
- `void clear()` - очищает контейнер
|
||||
- `void push_back()` - добавляет в конец value_type<>
|
||||
- `void pop_back()` - удаляет последний элемент
|
||||
- `reference back()` - возвращает ссылку на последний элемент
|
||||
- `reference front()` - возвращает ссылку на первый элемент
|
||||
- `iterator insert(iterator p, value_type<>)` - вставка перед позицией p, возвращает на новый элемент
|
||||
- `iterator erase(iterator p)` - удаляет, куда указывает, возвращает итератор на некст элемент
|
||||
- `iterator erase(iterator p1, iterator p2)` - c первого до последнего (не включительно)
|
||||
|
||||
для list, deque
|
||||
|
||||
- `void push_front(value_type<>)`
|
||||
- `void pop_front(value_type<>)`
|
||||
|
||||
Для bidirectional итераторов можно использовать
|
||||
|
||||
- `advance(p1, 3)` для плюса
|
||||
- `n = distance(p1, p2)` для вычитания
|
||||
|
||||
```cpp
|
||||
void f(vactor<char>& mas) {
|
||||
auto iter = mas.begin();
|
||||
|
||||
while (iter < mas.end()) {
|
||||
++iter;
|
||||
|
||||
if (iter != mas.end())
|
||||
iter = mas.erase(iter);
|
||||
}
|
||||
}
|
||||
```
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
# Шаблонные функции с контейнером на вход
|
||||
|
||||
-> написать шаблонную функцию, которая ищет макс значение в константном или неконстантном контейнере
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <typename T>
|
||||
typename T::value_type Max(const T& c) {
|
||||
// используем константные итераторы cbegin
|
||||
typename T::value_type max = *c.cbegin();
|
||||
|
||||
for (const auto& it : c) {
|
||||
if (*it > max) {
|
||||
max = *it;
|
||||
}
|
||||
max = *it > max ? *it : max
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
list<int> l = { 1, 2, 3, 4, 5 };
|
||||
cout << Max<list<int>>(l) << endl;
|
||||
|
||||
vector<long> v = { 1, 2, 3, 4, 5 };
|
||||
cout << Max<vector<long>>(v) << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Шаблонная функция, которая удваивает все элементы в контейнере
|
||||
Из [1, 2, 3] делает [1, 1, 2, 2, 3, 3]
|
||||
|
||||
```cpp
|
||||
// работает, но херня, много памяти жрёт
|
||||
template <typename T>
|
||||
void dbl(T& c) {
|
||||
T res;
|
||||
auto it = c.begin();
|
||||
while (it != c.end()) {
|
||||
res.push_back(*it);
|
||||
res.push_back(*it);
|
||||
++it;
|
||||
}
|
||||
|
||||
c = res;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// работает, всё правильно
|
||||
template <typename T>
|
||||
void dbl(T& c) {
|
||||
auto it = c.begin();
|
||||
// typename T::iterator it = c.begin(); - порой могут вот так просить на коллоквиуме
|
||||
|
||||
while (it != c.end()) {
|
||||
it = c.insert(++it, *it);
|
||||
++it;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
вход функции: 2 итератора, реверсирующая данную коллекцию
|
||||
Было [1, 2, 3] Стало [3, 2, 1]
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
void rever(T b, T e) {
|
||||
if (b == e) return; // для проверки на пустой контейнер
|
||||
|
||||
--e;
|
||||
|
||||
while (b != e) { // просто сравнивать нельзя у листов
|
||||
swap(*b++, *e); // нативный свап
|
||||
|
||||
if (b == e) break;
|
||||
|
||||
--e;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
функции подаётся 2 итератора, предикат и стандартное значение
|
||||
Предикат - объект с перегруженными круглыми скобками
|
||||
|
||||
```cpp
|
||||
template<typename T, typename P> // T - указатель P - предикат
|
||||
void f(T b, T, e, P pred, typename T::value_type val) {
|
||||
|
||||
}
|
||||
|
||||
// пример предиката
|
||||
struct Pred {
|
||||
bool operation()(int v) {
|
||||
return v % 3;
|
||||
}
|
||||
}
|
||||
|
||||
int main () {
|
||||
vector<int> v = {...};
|
||||
|
||||
f(v.begin(), v.end(), Pred(), 9);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Лямба-функции
|
||||
|
||||
Неименованные функции, которые можно просто вставить в выражение
|
||||
|
||||
```cpp
|
||||
int x = 5;
|
||||
auto ef = [x]() { cout << x; } // тут не обойтись без auto
|
||||
ef();
|
||||
auto ef = [](int a) { cout << a; }
|
||||
ef(x);
|
||||
```
|
||||
|
||||
В квадратных скобках - привязка к внешним элементам
|
||||
|
||||
- [] привязки нет
|
||||
- [=] привязываются все внешние
|
||||
- [&] по ссылке привязываются все внешние
|
||||
|
||||
В круглых - к тем, что передаются
|
||||
|
||||
## Алгоритм remove_if
|
||||
|
||||
```cpp
|
||||
vector <int> v = {2, 4, 5, 7, 9, 10};
|
||||
auto end = remove_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; })
|
||||
```
|
||||
|
||||
remove_if перемещает в хвост все значения, для которых предикат (лямбда-функция) верна. Возвращает указатель на начало хвоста
|
||||
Вывод: [5, 7, 9, 2, 4, 10]. end указывать будет на '2'
|
||||
|
||||
## 2 задание 3го контеста
|
||||
|
||||
> есть уже complex, complex stack. Добавление в стек через операцию <<
|
||||
|
||||
посчитать польско-инвер запись для комплексных чисел. Если попадается z - значение по умолчанию
|
||||
|
||||
> map - словарик. Содержит элементы 'ключ' - 'значение'
|
||||
|
||||
```cpp
|
||||
complex eval(const vector<string>& args, const complex& z) {
|
||||
complex stack st;
|
||||
map<string, function<void()>> mp; {
|
||||
{"z", [&st, &z]() { st = st << z; }}, // если попалось z, добавили в стек
|
||||
{";", [&st]() { st = ~st; }},
|
||||
... // все прочие +/-/... операции
|
||||
}
|
||||
|
||||
for (const auto& iter : args) {
|
||||
if (s[0] != '(') { // если строка не (re,im)
|
||||
mp[s](); // просто вызвали нужное
|
||||
} else {
|
||||
st = st << complex(s);
|
||||
}
|
||||
}
|
||||
|
||||
// ответ на верхушке стека
|
||||
return +st;
|
||||
}
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
# Наследования
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
int a;
|
||||
public:
|
||||
A(int x = 0) : a(x) {}
|
||||
void f() { cout << a; }
|
||||
};
|
||||
|
||||
class B : public/private/protected A/*, C*/ { // private by default
|
||||
int b;
|
||||
public:
|
||||
B(int x = 0, int y = 0) : A(x), b(y) {}
|
||||
void f() {
|
||||
cout << a << b; // error. A is private
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
A obj_a, *pa;
|
||||
B obj_b, *pb;
|
||||
pa = &obj_a;
|
||||
pb = &obj_b;
|
||||
|
||||
// при открытом наследовании
|
||||
pa = pb;
|
||||
pb = (B*)pa;
|
||||
|
||||
// при закрытом наследовании
|
||||
pa = (A*)pb;
|
||||
// pb = (B*)pa; - невозможно
|
||||
|
||||
*pa = &obj_a;
|
||||
pa->f(); // вызов из a
|
||||
*pa = &obj_b;
|
||||
pa->f(); // вызов тоже из a, т.к. не виртуальная функция
|
||||
}
|
||||
```
|
||||
|
||||
в ситуации любого наложения функций, происходит перекрытие имён
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
void f();
|
||||
}
|
||||
|
||||
class B : A {
|
||||
void f(int) { f(); } // error
|
||||
}
|
||||
```
|
||||
|
||||
конструкторы не наследуются
|
||||
|
||||
## консруктор копирования
|
||||
|
||||
```cpp
|
||||
B (const B &a) : A(a) {}
|
||||
```
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
# Семинар 6
|
||||
|
||||
## RTTI - Run Time Type Identification
|
||||
|
||||
- typeid
|
||||
- dynamic_cast
|
||||
|
||||
### typeid
|
||||
|
||||
> `typeid` возвращает тип объекта/указателя. Если указатель на класс с виртуальными функциями, вернёт именно тип объекта. Иначе - указателя.
|
||||
|
||||
Для `type_info` переопределённые операции и методы:
|
||||
|
||||
- ==
|
||||
- !-
|
||||
- .name
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
public:
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
int main () {
|
||||
A *pa = new B;
|
||||
B *pb;
|
||||
std::cout << typeid(*pa).name; // 1B (1 символ в имени)
|
||||
if (typeid(*pa) == typeid(B)) {
|
||||
pb = (B*)pa; // небезопасное приведение
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dynamic cast
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
public:
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
int main () {
|
||||
A *pa, a;
|
||||
B *pb, b;
|
||||
pa = &b;
|
||||
// безопасно приводит, вернёт не NULL в случае успеха
|
||||
pb = dynamic_cast<B*>(pa);
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
public:
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
int main () {
|
||||
A *pa, a;
|
||||
B *pb, b;
|
||||
A &pr = a;
|
||||
// B &rb = dynamic_cast<B&>(pa); // выкинет bad_cast
|
||||
}
|
||||
```
|
||||
|
||||
## Исключения
|
||||
|
||||
`try - throw - catch`
|
||||
|
||||
`terminate()` - в случае, если ничего не обработалось
|
||||
|
||||
приводится в `catch` указатели к константным могут
|
||||
|
||||
```cpp
|
||||
int f() {
|
||||
try {
|
||||
...
|
||||
throw 10;
|
||||
...
|
||||
throw "abc";
|
||||
...
|
||||
throw A();
|
||||
...
|
||||
} catch (int a) {
|
||||
...
|
||||
throw ...; // тогда обработается функцией выше
|
||||
...
|
||||
} catch (const char* s) {
|
||||
...
|
||||
} catch (A &x) {
|
||||
...
|
||||
} catch (...) { // все остальные исключения
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В случае возвращение класса, который наследуется от базового, "ловить" надо сначала производный, после - базовый
|
||||
Деструктор для создаваемого класса вызывается только после фулл обработки исключения (если catch сам вызвал throw)
|
||||
|
||||
```cpp
|
||||
int f() throw(int, char) {
|
||||
try {
|
||||
...
|
||||
throw 1.2;
|
||||
...
|
||||
} catch (double) {
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`unexpected()` - вызывается, если мы на внешнюю функцию передаём исключение типа, который не указан
|
||||
|
||||
```cpp
|
||||
// никакие не передавать вовне
|
||||
int f() throw();
|
||||
|
||||
after c++17 only:
|
||||
int f() noexcept;
|
||||
```
|
||||
|
||||
### Алгоритм обработки исключений
|
||||
|
||||
- создание временного объекта типа возвращаемого исключения
|
||||
- уничтожение объектов в `try` блоке
|
||||
- выход из `try`
|
||||
- подбор нужного обработчика
|
||||
- если больше исключений нет - деструктор временного объекта
|
||||
- если не обработано - выход к внешнему обработчику
|
||||
|
||||
```cpp
|
||||
5.14. Что напечатает следующая программа?
|
||||
struct S {
|
||||
S ( int a) {
|
||||
try {
|
||||
if (a > 0) throw *this ;
|
||||
else if (a < 0) throw 0;
|
||||
}
|
||||
catch ( S & ) {
|
||||
cout << “SCatch_S&” << endl;
|
||||
} catch (int ) { throw ; }
|
||||
cout << “SConstr” << endl;
|
||||
}
|
||||
S (const S & a) { cout << “Copy” << endl; }
|
||||
~S ( ) { cout << “Destr” << endl; }
|
||||
};
|
||||
int main ( ) {
|
||||
try {
|
||||
S s1( 0 ), s2 ( 5 );
|
||||
cout << “Main” << endl;
|
||||
}
|
||||
catch (S &) { cout << “MainCatch_S&” << endl; }
|
||||
catch ( ... ) { cout << “MainCatch_...” << endl; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Результат отработки программы:
|
||||
|
||||
```text
|
||||
Sconstr
|
||||
Copy
|
||||
Scatch_s&
|
||||
Destr
|
||||
Sconstr
|
||||
Main
|
||||
Destr
|
||||
Destr
|
||||
```
|
||||
|
||||
1
|
||||
14
|
||||
15
|
||||
CatchB
|
||||
bad_cast
|
||||
63
|
||||
63
|
||||
3
|
||||
...
|
||||
End
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
class string
|
||||
{
|
||||
int len; // количество памяти
|
||||
char* str;
|
||||
|
||||
public:
|
||||
string(const char* s = "") {
|
||||
len = strlen(s) + 1;
|
||||
str = new char[len];
|
||||
strcpy(str, s);
|
||||
}
|
||||
|
||||
char&
|
||||
operator[](int n) {
|
||||
return str[n];
|
||||
}
|
||||
|
||||
string
|
||||
operator+(string s) {
|
||||
string tmp;
|
||||
tmp.len = s.len + len - 1;
|
||||
tmp.str = new char[tmp.len];
|
||||
|
||||
strcpy(tmp.str, str);
|
||||
strcpy(tmp.str + len - 1, s.str);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// string
|
||||
// operator=(string s) {
|
||||
// if (s.str == str) {
|
||||
// return s;
|
||||
// }
|
||||
|
||||
// delete[] str;
|
||||
// len = s.len;
|
||||
// str = new char[len];
|
||||
// strcpy(str, s.str);
|
||||
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// ~string() { delete[] str; } почему-то с ним не работает (?)
|
||||
|
||||
void
|
||||
print() {
|
||||
std::cout << str << " " << len << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main() {
|
||||
string s1("abcd"), s2("qw"), s3;
|
||||
s2[1] = 'A';
|
||||
s2.print();
|
||||
s3 = s1 + s2;
|
||||
|
||||
s3.print();
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// -> написать шаблонную функцию, которая ищет макс значение в константном или неконстантном контейнере
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class Container>
|
||||
typename Container::value_type Max(const Container& c) {
|
||||
typename Container::value_type max = *c.cbegin();
|
||||
|
||||
for (auto it = c.cbegin(); it != c.cend(); ++it) {
|
||||
if (*it > max) {
|
||||
max = *it;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dbl(T& c) {
|
||||
auto it = c.begin();
|
||||
|
||||
while (it != c.end()) {
|
||||
it = c.insert(++it, *it);
|
||||
++it;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void rever(T b, T e) {
|
||||
if (b == e) return;
|
||||
|
||||
--e;
|
||||
|
||||
while (b != e) {
|
||||
swap(*b++, *e);
|
||||
|
||||
if (b == e) break;
|
||||
|
||||
--e;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct Pred {
|
||||
bool operator()(int x) {
|
||||
return x % 3;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename P> // T - указатель P - предикат
|
||||
void f(T b, T e, P pred, typename T::value_type val = {}) {
|
||||
while (b != e) {
|
||||
if (pred(*b)) {
|
||||
*b = val;
|
||||
}
|
||||
++b;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
list<int> l = { 1, 2, 3, 4, 5 };
|
||||
cout << Max<list<int>>(l) << endl;
|
||||
|
||||
f(l.begin(), l.end(), Pred());
|
||||
for (const auto& elem : l) {
|
||||
cout << elem << " ";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
// dbl(l);
|
||||
// rever(l.begin(), l.end());
|
||||
// for (const auto& elem : l) {
|
||||
// cout << elem << " ";
|
||||
// }
|
||||
// cout << endl;
|
||||
|
||||
vector<long> v = { 1, 3, 3, 4, 5 };
|
||||
cout << Max<vector<long>>(v) << endl;
|
||||
|
||||
// dbl(v);
|
||||
rever(v.begin(), v.end());
|
||||
for (const auto& elem : v) {
|
||||
cout << elem << " ";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
# Markdown Cheat Sheet
|
||||
|
||||
Thanks for visiting [The Markdown Guide](https://www.markdownguide.org)!
|
||||
|
||||
This Markdown cheat sheet provides a quick overview of all the Markdown syntax elements. It can’t cover every edge case, so if you need more information about any of these elements, refer to the reference guides for [basic syntax](https://www.markdownguide.org/basic-syntax/) and [extended syntax](https://www.markdownguide.org/extended-syntax/).
|
||||
|
||||
## Basic Syntax
|
||||
|
||||
These are the elements outlined in John Gruber’s original design document. All Markdown applications support these elements.
|
||||
|
||||
### Heading
|
||||
|
||||
# H1
|
||||
## H2
|
||||
### H3
|
||||
|
||||
### Bold
|
||||
|
||||
**bold text**
|
||||
|
||||
### Italic
|
||||
|
||||
*italicized text*
|
||||
|
||||
### Blockquote
|
||||
|
||||
> blockquote
|
||||
|
||||
### Ordered List
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
|
||||
### Unordered List
|
||||
|
||||
- First item
|
||||
- Second item
|
||||
- Third item
|
||||
|
||||
### Code
|
||||
|
||||
`code`
|
||||
|
||||
### Horizontal Rule
|
||||
|
||||
---
|
||||
|
||||
### Link
|
||||
|
||||
[Markdown Guide](https://www.markdownguide.org)
|
||||
|
||||
### Image
|
||||
|
||||

|
||||
|
||||
## Extended Syntax
|
||||
|
||||
These elements extend the basic syntax by adding additional features. Not all Markdown applications support these elements.
|
||||
|
||||
### Table
|
||||
|
||||
| Syntax | Description |
|
||||
| ----------- | ----------- |
|
||||
| Header | Title |
|
||||
| Paragraph | Text |
|
||||
|
||||
### Fenced Code Block
|
||||
|
||||
```
|
||||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"age": 25
|
||||
}
|
||||
```
|
||||
|
||||
### Footnote
|
||||
|
||||
Here's a sentence with a footnote. [^1]
|
||||
|
||||
[^1]: This is the footnote.
|
||||
|
||||
### Heading ID
|
||||
|
||||
### My Great Heading {#custom-id}
|
||||
|
||||
### Definition List
|
||||
|
||||
term
|
||||
: definition
|
||||
|
||||
### Strikethrough
|
||||
|
||||
~~The world is flat.~~
|
||||
|
||||
### Task List
|
||||
|
||||
- [x] Write the press release
|
||||
- [ ] Update the website
|
||||
- [ ] Contact the media
|
||||
|
||||
### Emoji
|
||||
|
||||
That is so funny! :joy:
|
||||
|
||||
(See also [Copying and Pasting Emoji](https://www.markdownguide.org/extended-syntax/#copying-and-pasting-emoji))
|
||||
|
||||
### Highlight
|
||||
|
||||
I need to highlight these ==very important words==.
|
||||
|
||||
### Subscript
|
||||
|
||||
H~2~O
|
||||
|
||||
### Superscript
|
||||
|
||||
X^2^
|
||||
Reference in New Issue
Block a user