Скачать презентацию Новые возможности языка Си Операторы new и Скачать презентацию Новые возможности языка Си Операторы new и

Лекция 02 - Новые возможности С++.pptx

  • Количество слайдов: 41

Новые возможности языка Си++ Новые возможности языка Си++

Операторы new и delete В состав языка вошли операторы new и delete, осуществляющие работу Операторы new и delete В состав языка вошли операторы new и delete, осуществляющие работу с динамической памятью на уровне языка Оператор new выделяет память под элемент или массив элементов Тип *p = new Тип() Тип *p = new Тип(инициализатор, . . . ) Тип *p = new Тип[кол-во элементов] Оператор delete освобождает память, выделенную ранее оператором new delete p. Object; delete [] p. Array;

Возможность объявления переменной при её первом использовании В отличие от языка C, локальные переменные Возможность объявления переменной при её первом использовании В отличие от языка C, локальные переменные в C++ могут быть объявлены в любом месте функции, а не только в начале блока Более того, это улучшает читаемость программы и является необходимым в ряде случаев Неизменным остается правило – переменная должна быть объявлена ДО ее первого использования Есть возможность объявления переменной цикла непосредственно в операторе for (int i = 0; i < 10; ++i) Время жизни такой переменной ограничено телом цикла (не соблюдается некоторыми старыми компияторами)

Перегрузка функций Перегрузка функций

Перегрузка функций Перегрузкой имени функции является его использование для обозначения разных операций над разными Перегрузка функций Перегрузкой имени функции является его использование для обозначения разных операций над разными типами Если несколько функций выполняют одно и то же действие с объектами различных типов, имеет смысл дать им одинаковые имена

Пример #include <stdio. h> void Print(int number) { printf( Пример #include void Print(int number) { printf("%d", number); } void Print(double number) { printf("%. 15 f", number); } void Print(const char* str) { printf("%s", str); } int main() { Print(1); printf("n"); Print(8. 0/3); printf("n"); Print("Hello Worldn"); return 0; }

Функции с различным количеством аргументов Функции с одним именем могут иметь различное число аргументов Функции с различным количеством аргументов Функции с одним именем могут иметь различное число аргументов В этом случае, будет вызвана та функция, количество формальных аргументов которой совпадает с количеством переданных параметров

Пример void Print(char ch) { putchar(ch); } void Print(char ch, int count) { while Пример void Print(char ch) { putchar(ch); } void Print(char ch, int count) { while (count--) { putchar(ch); } } int main() { Print('!'); putchar('n'); Print('!', 5); putchar('n'); return 0; }

Выбор нужной функции Для выбора функции из имеющихся вариантов компилятор сравнивает типы фактических аргументов, Выбор нужной функции Для выбора функции из имеющихся вариантов компилятор сравнивает типы фактических аргументов, указанные в вызове, с типами формальных аргументов всех описаний функций с данным именем В результате вызывается та функция, у которой типы формальных аргументов наилучшим образом сопоставились с параметрами вызова Типы возвращаемых значений функций не учитываются

Правила сопоставления параметров Правила сопоставления имеют следующие приоритеты (в порядке убывания): Точное сопоставление произошло Правила сопоставления параметров Правила сопоставления имеют следующие приоритеты (в порядке убывания): Точное сопоставление произошло без всяких преобразований типа или только с неизбежными преобразованиями Сопоставление с использованием стандартных целочисленных преобразований и преобразований с плавающей запятой char в int, short в int, float в double Сопоставление с использованием стандартных преобразований, определенных в §R. 4 int в double, derived * в base*, unsigned в int Сопоставление с использованием пользовательских преобразований §R. 12. 3 Сопоставление с использованием эллипсиса. . . в описании функции Выбирается та функция, у которой произошло сопоставление по наиболее приоритетному правилу

Возможные проблемы Если две или более функций с данным именем были сопоставлены по самому Возможные проблемы Если две или более функций с данным именем были сопоставлены по самому приоритетному правилу, компилятор выдаст сообщение об ошибке В этом случае требуется явно приводить аргументы к требуемым типам

Пример void Print(int number) { printf( Пример void Print(int number) { printf("%d", number); } void Print(double number) { printf("%. 15 f", number); } int main() { unsigned int arg = 2; Print(arg); // ошибка Print(static_cast(arg)); // OK return 0; }

Стандартные значения параметров Некоторые функции могут принимать больше параметров, чем в самых простых и Стандартные значения параметров Некоторые функции могут принимать больше параметров, чем в самых простых и часто используемых случаях Для гибкого использования этих функций могут применяться необязательные параметры

#include <stdio. h> void Clear. Array(int *array, unsigned size, int fill. Value = 0) #include void Clear. Array(int *array, unsigned size, int fill. Value = 0) { for (unsigned index = 0; index < size; ++index) array[index] = fill. Value; } void Print. Array(const int * array, unsigned size) { printf("{"); for (unsigned index = 0; index < size; ++index) { printf("%d", array[index]); if (index != (size - 1)) printf(" "); } printf("}n"); } OUTPUT: {0, 0, 0, 0} int main() {1, 1, 1, 1} { int arr[10]; unsigned const NUMBER_OF_ELEMENTS = sizeof(arr) / sizeof(*arr); Clear. Array(arr, NUMBER_OF_ELEMENTS); Print. Array(arr, NUMBER_OF_ELEMENTS); Clear. Array(arr, NUMBER_OF_ELEMENTS, 1); Print. Array(arr, NUMBER_OF_ELEMENTS); return 0; }

Ссылки Ссылку можно рассматривать как еще одно имя объекта Синтаксис <Тип> & означает ссылку Ссылки Ссылку можно рассматривать как еще одно имя объекта Синтаксис <Тип> & означает ссылку на <Тип> Применение Задание параметров функций Перегрузка операций

Ссылки в качестве параметров функций При передаче параметра в функцию по ссылке, функция принимает Ссылки в качестве параметров функций При передаче параметра в функцию по ссылке, функция принимает не копию аргумента, а ссылку на него При сложных типах аргументов это может дать прирост в скорости вызова функции Измененное внутри функции значение формального параметра приведет к изменению значения переданного аргумента Использование ссылок может быть альтернативным способом возврата значения из функции Если функция не изменяет значение аргумента, будет иметь смысл передать его по константной ссылке

Пример 1 #include <stdio. h> void Swap(int & a, int & b) { int Пример 1 #include void Swap(int & a, int & b) { int tmp = a; a = b; b = tmp; } int main() { int a = 1, b = 3; pritnf(“a=%d, b=%dn”, a, b); Swap(a, b); pritnf(“a=%d, b=%dn”, a, b); } OUTPUT a=1, b=3 a=3, b=1

Пример 2 struct Point { int x, y; }; void Print(Point const& pnt) { Пример 2 struct Point { int x, y; }; void Print(Point const& pnt) { printf("(x: %d, y: %d)n", pnt. x, pnt. y); } int main() { Point pnt = {10, 20}; Print(pnt); return 0; }

Инициализация ссылки Ссылка должна быть обязательно проинициализирована Должен существовать объект на который она ссылается Инициализация ссылки Ссылка должна быть обязательно проинициализирована Должен существовать объект на который она ссылается Синтаксис Тип & идентификатор = значение; Инициализация ссылки совершенно отличается от операции присваивания Будучи проинициализированной, присваивание ссылке нового значения изменяет значение ссылаемого объекта, а не значение ссылки

Пример #include <stdio. h> int main() { int i = 1; int j = Пример #include int main() { int i = 1; int j = 3; // инициализация ссылки int & ri = i; printf("i=%d, j=%dn", i, j); // присваивание значения объекту, на который ссылается ri ri = j; printf("i=%d, j=%dn", i, j); OUTPUT } i=1, j=3 i=3, j=3

Ссылки на временные объекты При инициализации ссылки объектом другого типа компилятор создает временный объект Ссылки на временные объекты При инициализации ссылки объектом другого типа компилятор создает временный объект нужного типа и использует его для инициализации ссылки На данный временный объект может ссылаться только константная ссылка То же самое происходит при инициализации ссылки значением константы Изменение значения объекта в данном случае не отражается на значении временного объекта

Пример int a = 1; int & ref. A = a; printf( Пример int a = 1; int & ref. A = a; printf("a = %dn", a); ++ref. A; printf("Now a = %dnn", a); const double & ref. Double. A = a; printf("ref. Double. A = %fn", ref. Double. A); ++a; printf("Now a = %d, ref. Double. A = %fn", a, ref. Double. A); OUTPUT: a = 1 Now a = 2 ref. Double. A = 2. 00000 Now a = 3, ref. Double. A = 2. 00000

Пространства имен позволяют логически сгруппировать классы, переменные и функции в некоторые именованные области Позволяют Пространства имен позволяют логически сгруппировать классы, переменные и функции в некоторые именованные области Позволяют избежать конфликта имен идентификаторов в различных модулях проекта Разбивают программу на функциональные единицы

#include <stdio. h> namespace math { int calculate. X 2(int x) { return x #include namespace math { int calculate. X 2(int x) { return x * x; } } namespace graphics { namespace shapes { struct rectangle { int x, y, w, h; }; struct circle { int x, y, r; }; } } namespace sound_player { void Play. Sound() { // sound playing code is placed here } } using namespace sound_player; int main() { int x = 5; int x 2 = math: : calculate. X 2(x); graphics: : shapes: : rectangle rect = {0, 0, 40, 30}; Play. Sound(); return 0; }

Стандартная библиотека шаблонов (STL) Программная библиотека, содержащая большое количество готового к использованию обобщенного кода Стандартная библиотека шаблонов (STL) Программная библиотека, содержащая большое количество готового к использованию обобщенного кода Контейнеры Итераторы Алгоритмы Все контейнеры, алгоритмы и итераторы в STL объявлены в пространстве имен std Стандарт запрещает программисту объявлять свои типы в данном пространстве имен

Контейнеры Классы, предназначенные для хранения элементов определенного типа STL содержит классы обобщенных реализаций различных Контейнеры Классы, предназначенные для хранения элементов определенного типа STL содержит классы обобщенных реализаций различных контейнеров, которые можно использовать с элементами различных типов В STL поддерживаются 2 вида контейнеров Последовательные Ассоциативные

Контейнеры в STL Последовательные контейнеры Строка (basic_string, wstring) Вектор (vector) Двусвязный список (list) Двусторонняя Контейнеры в STL Последовательные контейнеры Строка (basic_string, wstring) Вектор (vector) Двусвязный список (list) Двусторонняя очередь (deque) Ассоциативные контейнеры карта (map, multimap) множество (set, multiset) Контейнеры-адаптеры Стек (stack) Очередь (queue) Очередь с приоритетом (priority_queue)

Строка std: : string Контейнер, предназначенный для хранения строк произвольной длины В качестве элементов Строка std: : string Контейнер, предназначенный для хранения строк произвольной длины В качестве элементов строк могут выступать элементы типа char (string), wchar_t (wstring) или определяемые пользователем типы (basic_string) Данный контейнер автоматизирует задачу управления памятью, занимаемой символами строки и предоставляет набор методов для осуществления операций над строками Для работы с данным классом строк необходимо подключить заголовочный файл

Пример #include <string> #include <stdio. h> using namespace std; int main(int argc, char *argv[]) Пример #include #include using namespace std; int main(int argc, char *argv[]) { string hello = “Hello”; string world(“world”); string hello. World = hello + “ “ + world; size_t len = hello. World. length(); printf(“%sn”, hello. World. c_str()); return 0; }

Вектор std: : vector Контейнер для хранения динамического массива элементов произвольного типа Как и Вектор std: : vector Контейнер для хранения динамического массива элементов произвольного типа Как и строка, вектор автоматизирует процесс управления памятью, занимаемой элементами массива Везде, где возможно, рекомендуется использовать класс vector как альтернативу динамическому выделению массивов объектов при помощи оператора new К элементам массива предоставляется индексированный доступ Для использования данного класса необходимо подключить заголовочный файл

Пример #include <vector> #include <string> using namespace std; int main(int argc, char *argv[]) { Пример #include #include using namespace std; int main(int argc, char *argv[]) { // создаем массив целых чисел, содержащий 100 элементов vector vector. Of. Int(100); vector vector. Of. String; vector. Of. Int. push_back(10); vector. Of. String. push_back(“Hello”); std: : string hello = vector. Of. String[0]; size_t number. Of. Items = vector. Of. String. size(); return 0; }

Двусвязный список std: : list Реализовывает двусвязный список элементов произвольного типа К элементам списка Двусвязный список std: : list Реализовывает двусвязный список элементов произвольного типа К элементам списка осуществляется последовательный доступ при помощи итераторов Вставка и удаление элементов из произвольного места списка осуществляется за постоянное время Для начала работы с данным контейнером необходимо подключить заголовочный файл

Пример #include <list> #include <string> #include <iostream> using namespace std; int main(int argc, char Пример #include #include #include using namespace std; int main(int argc, char *argv[]) { list list. Of. Strings; list. Of. Strings. push_back(“One”); list. Of. Strings. push_back(“Two”); list. Of. Strings. push_back(“Three”); for (list: : iterator it = list. Of. Strings. begin(); it != list. Of. Strings. end(); ++it) { std: : string const& item = *it; cout << item << “, “; } return 0; }

Двусторонняя очередь std: : deque Аналогична вектору, но обеспечивает эффективную вставку и удаление элементов Двусторонняя очередь std: : deque Аналогична вектору, но обеспечивает эффективную вставку и удаление элементов не только в конце, но и в начале очереди Для использования необходимо подключить заголовочный файл

Классы std: : map и std: : multimap Ассоциативный контейнер, хранящий пары «ключ» - Классы std: : map и std: : multimap Ассоциативный контейнер, хранящий пары «ключ» - «значение» Позволяет отображать элементы одного типа в элементы другого или того же самого типа map – все ключи уникальные multimap – допускается дублирование ключей Для подключения данных классов необходимо подключить заголовочный файл

Пример #include <map> #include <string> #include <iostream> using namespace std; int main(int argc, char Пример #include #include #include using namespace std; int main(int argc, char *argv[]) { map dictionary; map. insert(pair(“Cat”, “Кошка”)); map[“Dog”] = “Собака”; map[“Mouse”] = “Мышь”; cout << map[“Dog”] << “n”; return 0; }

Классы множеств std: : set и std: : multiset Ассоциативный контейнер, хранящий множество элементов Классы множеств std: : set и std: : multiset Ассоциативный контейнер, хранящий множество элементов определенного типа set – дублирование элементов не допускается multiset – дублирование элементов допускается Для использования данных классов необходимо подключить заголовочный файл

Пример #include <set> #include <string> #include <iostream> using namespace std; int main(int argc, char Пример #include #include #include using namespace std; int main(int argc, char *argv[]) { set prime. Numbers; prime. Numbers. insert(2); prime. Numbers. insert(3); prime. Numbers. insert(5); if (prime. Numbers. find(3) != prime. Numbers. end()) { cout << “ 3 is a prime numbern”; } set male. Names; male. Names. insert(“John”); male. Names. insert(“Peter”); return 0; }

Итераторы Итератор – объект, позволяющий программисту осуществлять перебор элементов контейнера вне зависимости от деталей Итераторы Итератор – объект, позволяющий программисту осуществлять перебор элементов контейнера вне зависимости от деталей его реализации Например, осуществлять вставку диапазона элементов одного контейнера в другой Итераторы используются в STL для доступа к элементам контейнеров Обобщенные реализации алгоритмов используют итераторы для обработки элементов контейнеров Итератор – связующее звено между контейнером и алгоритмом

Алгоритмы Обобщенных функции, реализующие типичные алгоритмы над элементами контейнеров Сортировка, поиск, поэлементная обработка Алгоритмы Алгоритмы Обобщенных функции, реализующие типичные алгоритмы над элементами контейнеров Сортировка, поиск, поэлементная обработка Алгоритмы в STL не работают с контейнерами напрямую Вместо этого алгоритмы используют итераторы, задающие определенные элементы или диапазоны элементов контейнера Для работы с алгоритмами STL необходимо подключить заголовочный файл

Пример #include <string> <vector> <list> <iterator> using namespace std; int main(int argc, char *argv[]) Пример #include using namespace std; int main(int argc, char *argv[]) { vector names; names. push_back(“Peter”); names. push_back(“Ivan”); names. push_back(“John”); list names. List; sort(names. begin(), names. end()); copy(names. begin(), names. end(), names. List. end()); return 0; }