C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц Страница 5
- Категория: Компьютеры и Интернет / Программирование
- Автор: Яцек Галовиц
- Страниц: 121
- Добавлено: 2023-07-15 16:10:03
C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц» бесплатно полную версию:С++ — объектно-ориентированный язык программирования, без которого сегодня немыслима промышленная разработка ПО. В этой замечательной книге описана работа с контейнерами, алгоритмами, вспомогательными классами, лямбда-выражениями и другими интересными инструментами, которыми богат современный С++. Освоив материал, вы сможете коренным образом пересмотреть привычный подход к программированию.
Преимущество издания — в подробном описании стандартной библиотеки шаблонов С++, STL. Ее свежая версия была выпущена в 2017 году. В книге вы найдете более 90 максимально реалистичных примеров, которые демонстрируют всю мощь STL. Многие из них станут базовыми кирпичиками для решения более универсальных задач.
Вооружившись этой книгой, вы сможете эффективно использовать С++17 для создания высококачественного и высокопроизводительного ПО, применимого в различных отраслях.
C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц читать онлайн бесплатно
int fraction, remainder;
const bool success {divide_remainder(16, 3, fraction, remainder)};
if (success) {
std::cout << "16/3 is " << fraction << " with a remainder of "
<< remainder << '\n';
}
Многие все еще предпочитают делать именно так, а не возвращать пары, кортежи и структуры. При этом они приводят следующие аргументы: код работает быстрее, поскольку мы не создаем промежуточные копии этих значений. Но для современных компиляторов это неверно — они изначально оптимизированы так, что подобные копии не создаются.
Помимо того, что аналогичной возможности нет в языке C, возврат сложных структур в качестве выходных параметров долгое время считался медленным, поскольку объект сначала нужно инициализировать в возвращающей функции, а затем скопировать в переменную, которая должна будет содержать возвращаемое значение на вызывающей стороне. Современные компиляторы поддерживают оптимизацию возвращаемых значений (return value optimization, RVO), что позволяет избежать создания промежуточных копий.
Ограничиваем область видимости переменных в выражениях if и switch
Максимальное ограничение области видимости переменных считается хорошим тоном. Иногда, однако, переменная должна получить какое-то значение, а потом нужно его проверить на соответствие тому или иному условию, чтобы продолжить выполнение программы. Для этих целей в С++17 была введена инициализация переменных в выражениях if и switch.
Как это делается
В данном примере мы воспользуемся новым синтаксисом в обоих контекстах, чтобы увидеть, насколько это улучшит код.
□ Выражение if. Допустим, нужно найти символ в таблице символов с помощью метода find контейнера std::map:
if (auto itr (character_map.find(c)); itr != character_map.end()) {
// *itr корректен. Сделаем с ним что-нибудь.
} else {
// itr является конечным итератором. Не разыменовываем.
}
// здесь itr недоступен
□ Выражение switch. Так выглядит код получения символа из пользовательского ввода и его одновременная проверка в выражении switch для дальнейшего управления персонажем компьютерной игры:
switch (char c (getchar()); c) {
case 'a': move_left(); break;
case 's': move_back(); break;
case 'w': move_fwd(); break;
case 'd': move_right(); break;
case 'q': quit_game(); break;
case '0'...'9': select_tool('0' - c); break;
default:
std::cout << "invalid input: " << c << '\n';
}
Как это работает
Выражения if и switch с инициализаторами по сути являются синтаксическим сахаром. Два следующих фрагмента кода эквивалентны:
До C++17:
{
auto var (init_value); if (condition) {
// Ветвь A. К переменной var можно получить доступ
} else {
// Ветвь B. К переменной var можно получить доступ
}
// К переменной var все еще можно получить доступ
}
Начиная с C++17:
if (auto var (init_value); condition) {
// Ветвь A. К переменной var можно получить доступ
} else {
// Ветвь B. К переменной var можно получить доступ
}
// К переменной var больше нельзя получить доступ
То же верно и для выражений switch.
До C++17:
{
auto var (init_value); switch (var) {
case 1: ...
case 2: ...
...
}
// К переменной var все еще можно получить доступ
}
Начиная с C++17:
switch (auto var (init_value); var) {
case 1: ...
case 2: ...
...
}
// К переменной var больше нельзя получить доступ
Благодаря описанному механизму область видимости переменной остается минимальной. До С++17 этого можно было добиться только с помощью дополнительных фигурных скобок, как показано в соответствующих примерах. Короткие жизненные циклы уменьшают количество переменных в области видимости, что позволяет поддерживать чистоту кода и облегчает рефакторинг.
Дополнительная информация
Еще один интересный вариант — ограниченная область видимости критических секций. Рассмотрим следующий пример:
if (std::lock_guard<std::mutex> lg {my_mutex}; some_condition) {
// Делаем что-нибудь
}
Сначала создается std::lock_guard. Этот класс принимает мьютекс в качестве аргумента конструктора. Он запирает мьютекс в конструкторе, а затем, когда выходит из области видимости, отпирает его в деструкторе. Таким образом, невозможно забыть отпереть мьютекс. До появления С++17 требовалась дополнительная пара скобок, чтобы определить область, где мьютекс снова откроется.
Не менее интересный пример — это область видимости слабых указателей. Рассмотрим следующий фрагмент кода:
if (auto shared_pointer (weak_pointer.lock()); shared_pointer != nullptr) {
// Да, общий объект еще существует
} else {
// К указателю shared_pointer можно получить доступ, но он является нулевым
}
// К shared_pointer больше нельзя получить доступ
Это еще один пример с бесполезной переменной shared_pointer. Она попадает в текущую область видимости, несмотря на то что потенциально является бесполезной за пределами условного блока if или дополнительных скобок!
Выражения if с инициализаторами особенно хороши при работе с устаревшими API, имеющими выходные параметры:
if (DWORD exit_code; GetExitCodeProcess(process_handle, &exit_code)) {
std::cout << "Exit code of process was: " << exit_code << '\n';
}
// Бесполезная переменная exit_code не попадает за пределы условия if
GetExitCodeProcess — функция API ядра Windows. Она возвращает код для заданного дескриптора процесса, но только в том случае, если данный дескриптор корректен. После того как мы покинем этот условный блок, переменная станет бесполезной, поэтому она не нужна в нашей области видимости.
Возможность инициализировать переменные внутри блоков if, очевидно, очень полезна во многих ситуациях, особенно при работе с устаревшими API, которые используют выходные параметры.
Всегда ограничивайте области видимости с помощью инициализации в выражениях if и switch. Это позволит сделать код более компактным, простым для чтения, а в случае рефакторинга его будет проще перемещать.
Новые правила инициализатора с фигурными скобками
В C++11 появился новый синтаксис инициализатора с фигурными скобками {}. Он предназначен как для агрегатной инициализации, так и для вызова обычного конструктора. К сожалению, когда вы
Жалоба
Напишите нам, и мы в срочном порядке примем меры.