Похожие презентации:
Лекция 8. Расширение возможностей С++ в новых стандартах языка (1)
1. Лекция 8. Расширение возможностей С++ в новых стандартах языка
Виктор Михайлович Гриняк,профессор
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
2. Мотивы расширения стандартов языка
В 90-х и до середины нулевых годов С++ был самымраспространённым языком в профессиональной разработке
программ общего назначения.
Самый устойчивый вариант языка был зафиксирован стандартом
ANSI C++ (C++99).
В 2000-х годах получили распространение новые типы программ:
кроссплатформенных, мобильных, приложений для браузеров и т.п.
Для их реализации было создано много новых возможностей.
Возникла необходимость их реализации в С++.
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
3. Основные новшества, реализованные в новых стандартах языка С++11, С++14, С++17, С++20
• определение типа данных во время компиляции (auto)• лямбда-выражения
• кортежи и структурное связывание
• оператор for в форме for each
• семантика перемещения (move семантика)
• много других https://github.com/AnthonyCalandra/modern-cppfeatures
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
4. Определение типа данных во время компиляции
Переменные, тип которых определён как auto, определяют свой тип вовремя компиляции по косвенным признакам: типу данных, которым
они инициализируются, типу параметров функции и т.п.
auto an_int = 26; // при компиляции тип данных будет определен как int
auto a_bool = false; // как bool
auto a_float = 26.04f; // как float
auto ptr = &a_float; // как указатель
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
5. Определение типа данных во время компиляции
Тип параметров функции и возвращаемых данных тоже может быть auto.auto merge(auto a, auto b)
{
std::vector c = do_something(a, b);
return c;
}
std::vector<int> a = { ... }; // какие-то данные
std::vector<int> b = { ... }; // какие-то данные
auto c = merge(a, b);
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
6. Лямбда-выражения
Лямбда-выражения берут начало в функциональной парадигмепрограммирования, где функция считается объектом и может присваиваться
и передаваться как параметр. Последние стандарты языка С++ дают
возможность использовать некоторые элементы функционального
программирования, что даёт возможность реализации целого ряда удобных
абстракций.
Лямбда-выражения являются безымянными функциональными объектами и
захватывают переменные в различных областях на основе некоторого
краткого синтаксиса.
Лямбда-выражения полезны, если нужно сделать в коде быстрое и
небольшое изменение, без написания для этого отдельной функции. Другое
довольно распространённое использование лямбда выражения –
определение операции сравнения.
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
7. Лямбда-выражения
std::vector< std::pair<int, int> > data = { {1, 3},{7, 6},
{12, 4} };
std::sort( data.begin(),
data.end(),
[](auto a, auto b) {
return a.second < b.second;
}
);
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
8. Лямбда-выражения
Квадратные скобки определяют область действия лямбда-выражения, задаютполномочия для доступа к локальным переменным.
[ ] - ничего не захватывает. Таким образом, вы не можете использовать любую
локальную переменную внешней области видимости в лямбда-выражении. Вы
можете использовать только параметры.
[=] - захватывает локальные объекты (локальные переменные, параметры) в
области видимости по значению. Вы можете использовать, но не изменять их.
[&] - захватывает локальные объекты (локальные переменные, параметры) в
области видимости по ссылке. Вы можете изменить их, как в примере,
приведённом ниже.
[this] - захватывает этот указатель по значению.
[a, &b] - захватывает объект a по значению, объект b по ссылке.
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
9. Примеры лямбда-выражений
int x = 1;auto getX = [=] { return x; };
getX(); // == 1
auto addX = [=](int y) { return x + y; };
addX(1); // == 2
auto getXRef = [&]() -> int& { return x; };
getXRef(); // х будет возвращена по ссылке
auto f1 = [&x] { x = 2; }; // OK: x захватывается по ссылке и может изменяться
auto f2 = [x] { x = 2; }; // ОШИБКА, х не может изменяться, так как захвачен по значению
auto f3 = [x]() mutable { x = 2; }; // OK: разрешается изменять захваченные переменные
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
10. Кортежи и структурное связывание
auto user_info = std::make_tuple("M", "Chowdhury", 25); // здесь auto используется,чтобы уменьшить описание типов
// чтобы получить доступ к данным
std::get<0>(user_info);
std::get<1>(user_info);
std::get<2>(user_info);
Доступ к данным можно получить и так
auto [first_name, last_name, age] = user_info;
Последняя команда [ …. ] называется структурным связыванием.
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
11. Оператор for в форме for each
Синтаксис цикла for в форме for each следующий:for (объявление_элемента : массив)
{
}
Пример:
int math[] = { 0, 1, 4, 5, 7, 8, 10, 12, 15, 17, 30, 41};
for (int number : math) // итерация по массиву math
{
std::cout << number << ' '; // получаем доступ к элементу массива в этой
// итерации через переменную number
}
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
12. Оператор for в форме for each
Поскольку объявляемый элемент цикла foreach должен быть того же типа, что и элементымассива, то это идеальный случай для использования ключевого слова auto.
int math[] = { 0, 1, 4, 5, 7, 8, 10, 12, 15, 17, 30, 41};
for (auto number : math) // итерация по массиву math
{
std::cout << number << ' ';
}
Циклы foreach работают не только с фиксированными массивами, но также и с любыми
структурами, для которых задан итератор.
Доступ к элементам можно получить также с помощью ссылки. Это предотвращает
копирование элементов в тех случаях, когда оно не требуется или нежелательно.
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
13. move семантика
Семантика перемещения (move semantics) - это собирательное название специализированных средств языкаC++, которые предназначены для осуществления перемещения данных (вместо их копирования)
Появление в С++ семантики перемещения требует при разработке сложных классов, работающих с памятью,
помимо определения конструктора копирования, деструктора и копирующего (обычного) оператора
присваивания определять дополнительно конструктор перемещения и перемещающий оператор
присваивания.
class MemoryBlock
{
MemoryBlock(MemoryBlock& other)
{
// конструктор копирования }
MemoryBlock(MemoryBlock&& other)
{
// конструктор перемещения }
};
© В.М. Гриняк, проф. каф. Информационных технологий и систем ВГУЭС
int main()
{
MemoryBlock block;
MemoryBlock copyBlock = block; // Здесь вызовется конструктор
копирования
MemoryBlock moveBlock = std::move(block); // Здесь вызовется
конструктор перемещения
}