На этом шаге мы рассмотрим модифицирующие алгоритмы.
Модифицирующие алгоритмы изменяют значения элементов. Модификация производится непосредственно внутри интервала или в процессе копирования в другой интервал. Если элементы копируются в приемный интервал, исходный интервал остается без изменений. В таблице 1 перечислены модифицирующие алгоритмы стандартной библиотеки C++.
Название | Описание |
---|---|
for_each() | Выполняет операцию с каждым элементом |
сору() | Копирует интервал, начиная с первого элемента |
copy_backwards() | Копирует интервал, начиная с последнего элемента |
transform() | Модифицирует (и копирует) элементы; объединяет элементы двух интервалов |
merge() | Производит слияние двух интервалов |
swap_ranges() | Меняет местами элементы двух интервалов |
fill() | Заменяет каждый элемент заданным значением |
fill_n() | Заменяет n элементов заданным значением |
generate() | Заменяет каждый элемент результатом операции |
generate_n() | Заменяет n элементов результатом операций |
replace() | Заменяет элементы с заданным значением другим значением |
replace_if() | Заменяет элементы, соответствующие критерию, заданным значением |
replace_copy() | Заменяет элементы с заданным значением при копировании интервала |
replace_copy_if() | Заменяет элементы, соответствующие критерию, при копировании интервала |
В группе модифицирующих алгоритмов центральное место занимают алгоритмы for_each() и transform(). Оба алгоритма используются для модификации элементов последовательности, однако работают они по-разному.
void square (int& elem) // Передача по ссылке { elem = elem * elem; // Прямое присваивание вычисленного значения } . . . . . for_each(coll.begin(), coll.end(), // Интервал square); // Операция
void square (int elem) // Передача по значению { return elem * elem; // Возврат вычисленного значения } . . . . . for_each(coll.begin(), coll.end(), // Источник coll.begin(), // Приемник square); // Операция
Алгоритм transform() работает чуть медленнее, потому что требует возвращения и присваивания результата вместо прямой модификации элемента. С другой стороны, этот подход более гибок, поскольку он также может использоваться для модификации элементов в процессе копирования в другой интервал. Кроме того, у алгоритма transform() есть еще одна версия, которая позволяет обрабатывать и комбинировать элементы из двух разных интервалов.
Строго говоря, алгоритм merge() мог бы и не входить в список модифицирующих алгоритмов. Он требует сортировки своих интервалов-источников, поэтому его правильнее было бы включить в список алгоритмов упорядоченных интервалов. Но на практике алгоритм merge() также успешно справляется со слиянием неупорядоченных интервалов. Конечно, результат тоже оказывается неупорядоченным. И все же для надежности стоит вызывать merge() только для упорядоченных интервалов.
Учтите, что элементы ассоциативных алгоритмов объявляются константными, чтобы алгоритм не мог нарушить порядок следования элементов вследствие модификации их значений. Это означает, что ассоциативные контейнеры не могут выступать в качестве приемника для модифицирующих алгоритмов.
Кроме модифицирующих алгоритмов в стандартной библиотеке C++ выделена отдельная группа модифицирующих алгоритмов для упорядоченных интервалов.
На следующем шаге мы рассмотрим алгоритмы удаления.