std::ranges::replace
C++20 引入的算法,用于将范围中所有等于某个特定值的元素替换为另一个值。它是 std::replace
的范围版本,支持范围操作和更现代的 C++ 风格。
功能
-
遍历范围
r
,将所有等于old_value
的元素替换为new_value
。 -
替换是就地(in-place)进行的,即直接修改输入源范围。
Defined in header | ||
Call signature | ||
(1) | ||
template< std::input_iterator I, std::sentinel_for<I> S, class T1, class T2, class Proj = std::identity > | (since C++20) (until C++26) | |
template< std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity, | (since C++26) | |
(2) | ||
template< ranges::input_range R, class T1, class T2, class Proj = std::identity > | (since C++20) (until C++26) | |
template< ranges::input_range R, class Proj = std::identity, | (since C++26 |
-
参数:
-
r
: 要操作的范围,可以是任何满足ranges::input_range
的范围(如容器、数组等)。 -
old_value
: 需要被替换的值。 -
new_value
: 替换后的新值。
-
-
返回值: 无(
void
),直接修改输入范围。
示例 1
#include <iostream>
#include <vector>
#include <algorithm> // std::ranges::replace
#include <ranges> // C++20 范围库
int main() {
// 示例 1: 替换 vector 中的元素
std::vector<int> vec = {1, 2, 3, 2, 4, 2, 5};
// 将所有值为 2 的元素替换为 99
std::ranges::replace(vec, 2, 99);
// 输出结果
std::cout << "After replace: ";
for (int i : vec) {
std::cout << i << " ";
}
std::cout << "\n";
// 示例 2: 替换数组中的元素
int arr[] = {10, 20, 10, 30, 10, 40};
// 将所有值为 10 的元素替换为 100
std::ranges::replace(arr, 10, 100);
// 输出结果
std::cout << "After replace: ";
for (int i : arr) {
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
输出:
After replace: 1 99 3 99 4 99 5
After replace: 100 20 100 30 100 40
详解
-
范围支持:
-
std::ranges::replace
支持任何满足ranges::input_range
的范围,包括标准容器(如std::vector
、std::list
)、原生数组等。 -
与传统的
std::replace
相比,std::ranges::replace
更符合现代 C++ 的范围操作风格。
-
-
就地修改:
-
std::ranges::replace
直接修改输入范围,而不是返回一个新的范围。
-
-
复杂度:
-
时间复杂度为 O(N),其中 N 是范围的大小。算法会遍历整个范围一次。
-
-
适用场景:
-
当需要将范围中所有等于某个值的元素替换为另一个值时使用。
-
例如,将容器中的所有
0
替换为-1
,或者将所有空字符串替换为默认值。
-
std::ranges::replace_if
C++20 引入的算法,用于将范围中满足特定条件的元素替换为另一个值。它是 std::replace_if
的范围版本,支持范围操作和更现代的 C++ 风格。
功能
-
遍历范围
r
,对所有满足谓词pred
的元素替换为new_value
。 -
替换是就地(in-place)进行的,即直接修改输入源范围。
template< std::input_iterator I, std::sentinel_for<I> S, class T, class Proj = std::identity, | (since C++20) (until C++26) | |
template< std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity, | (since C++26) | |
(4) | ||
template< ranges::input_range R, class T, class Proj = std::identity, std::indirect_unary_predicate< | (since C++20) (until C++26) | |
template< ranges::input_range R, class Proj = std::identity, class T = std::projected_value_t<ranges::iterator_t<R>, Proj>, | (since C++26) |
-
参数:
-
r
: 要操作的范围,可以是任何满足ranges::input_range
的范围(如容器、数组等)。 -
pred
: 一元谓词(函数或可调用对象),用于判断是否需要替换元素。如果pred(e)
返回true
,则元素e
会被替换。 -
new_value
: 替换后的新值。
-
-
返回值: 无(
void
),直接修改输入范围。
示例 1
#include <iostream>
#include <vector>
#include <algorithm> // std::ranges::replace_if
#include <ranges> // C++20 范围库
int main() {
// 示例 1: 替换 vector 中所有偶数元素为 -1
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 将所有偶数替换为 -1
std::ranges::replace_if(vec, [](int x) { return x % 2 == 0; }, -1);
// 输出结果
std::cout << "After replace_if: ";
for (int i : vec) {
std::cout << i << " ";
}
std::cout << "\n";
// 示例 2: 替换数组中所有大于 10 的元素为 0
int arr[] = {5, 12, 8, 15, 3, 20};
// 将所有大于 10 的元素替换为 0
std::ranges::replace_if(arr, [](int x) { return x > 10; }, 0);
// 输出结果
std::cout << "After replace_if: ";
for (int i : arr) {
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
输出:
After replace_if: 1 -1 3 -1 5 -1 7 -1 9
After replace_if: 5 0 8 0 3 0
详解
-
范围支持:
-
std::ranges::replace_if
支持任何满足ranges::input_range
的范围,包括标准容器(如std::vector
、std::list
)、原生数组等。 -
与传统的
std::replace_if
相比,std::ranges::replace_if
更符合现代 C++ 的范围操作风格。
-
-
谓词:
-
谓词
pred
是一个一元函数或可调用对象,接受范围中的元素作为参数,并返回bool
值。 -
如果
pred(e)
返回true
,则元素e
会被替换为new_value
。
-
-
就地修改:
-
std::ranges::replace_if
直接修改输入范围,而不是返回一个新的范围。
-
-
复杂度:
-
时间复杂度为 O(N),其中 N 是范围的大小。算法会遍历整个范围一次。
-
-
适用场景:
-
当需要根据条件替换范围中的元素时使用。
-
例如,将所有负数替换为
0
,或将所有空字符串替换为默认值。
-
std::ranges::replace_copy
C++20 引入的算法,用于将输入范围内的元素复制到输出范围,同时替换满足条件的值。它是 std::replace_copy 的范围化版本,支持更灵活的迭代器和范围操作。
功能
将输入范围 [first, last) 的元素复制到输出范围,同时将所有等于 old_value 的元素替换为 new_value。原始输入范围不会被修改。
Defined in header | ||
Call signature | ||
(1) | ||
template< std::input_iterator I, std::sentinel_for<I> S, class T1, class T2, std::output_iterator<const T2&> O, class Proj = std::identity > | (since C++20) (until C++26) | |
template< std::input_iterator I, std::sentinel_for<I> S, class O, class Proj = std::identity, | (since C++26) | |
(2) | ||
template< ranges::input_range R, class T1, class T2, std::output_iterator<const T2&> O, class Proj = std::identity > | (since C++20) (until C++26) | |
template< ranges::input_range R, class O, class Proj = std::identity, |
-
参数:
-
r
: 输入范围,可以是任何满足ranges::input_range
的范围(如容器、数组等)。 -
result
: 目标范围的起始迭代器,用于存储复制后的结果。 -
old_value
: 需要被替换的值。 -
new_value
: 替换后的新值。
-
-
返回值:
{last, result + N}.
返回
reverse_copy_result
,包含两个成员: in
:输入范围的结束迭代器。out
:输出范围的结束迭代器。
示例 1:
#include <iostream>
#include <vector>
#include <algorithm> // std::ranges::replace_copy
#include <ranges> // C++20 范围库
int main() {
// 示例 1: 替换 vector 中的元素并复制到另一个 vector
std::vector<int> src = {1, 2, 3, 2, 4, 2, 5};
std::vector<int> dst(src.size()); // 目标范围,大小与源范围相同
// 将所有值为 2 的元素替换为 99,并复制到 dst
auto result = std::ranges::replace_copy(src, dst.begin(), 2, 99);
// 输出结果
std::cout << "Source after replace_copy: ";
for (int i : src) {
std::cout << i << " ";
}
std::cout << "\n";
std::cout << "Destination after replace_copy: ";
for (auto it = dst.begin(); it != result.out; ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
// 示例 2: 替换数组中的元素并复制到另一个数组
int src_arr[] = {10, 20, 10, 30, 10, 40};
int dst_arr[6]; // 目标数组,大小与源数组相同
// 将所有值为 10 的元素替换为 100,并复制到 dst_arr
auto end_arr = std::ranges::replace_copy(src_arr, dst_arr, 10, 100);
// 输出结果
std::cout << "Source array after replace_copy: ";
for (int i : src_arr) {
std::cout << i << " ";
}
std::cout << "\n";
std::cout << "Destination array after replace_copy: ";
for (auto it = std::begin(dst_arr); it != end_arr.out; ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
return 0;
}
输出:
Source after replace_copy: 1 2 3 2 4 2 5
Destination after replace_copy: 1 99 3 99 4 99 5
Source array after replace_copy: 10 20 10 30 10 40
Destination array after replace_copy: 100 20 100 30 100 40
详解
-
范围支持:
-
std::ranges::replace_copy
支持任何满足ranges::input_range
的输入范围,以及任何满足ranges::output_iterator
的目标迭代器。 -
与传统的
std::replace_copy
相比,std::ranges::replace_copy
更符合现代 C++ 的范围操作风格。
-
-
不修改输入范围:
-
std::ranges::replace_copy
不会修改输入范围,而是将结果复制到目标范围。
-
-
返回值:
-
返回目标范围的结束迭代器,可以用于确定复制后的有效范围。
-
-
复杂度:
-
时间复杂度为 O(N),其中 N 是输入范围的大小。算法会遍历整个输入范围一次。
-
-
适用场景:
-
当需要复制一个范围并替换其中的某些元素时使用。
-
例如,将容器中的所有
0
替换为-1
,并将结果存储到另一个容器中。
-
关键点
不修改原范围:输入范围保持不变,结果写入输出范围。
输出迭代器:需确保输出范围有足够空间(或使用 back_inserter 动态扩展)。
复杂度:线性复杂度 O(N),N 为输入范围大小。
迭代器要求:输入范围需要是双向迭代器(支持反向遍历)。
对比 reverse 和 reverse_copy
| 特性 | std::ranges::reverse | std::ranges::reverse_copy |
是否修改原范围 是 否
输出目标 无(原地修改) | 指定输出范围
典型用例 需要原地逆序的场景 需要保留原始数据的逆序副本的场景
通过 std::ranges::reverse_copy,可以方便地生成逆序副本,适用于需要保留原始数据顺序的场景。
返回值详解
in
类型为输入迭代器 I,指向输入范围的末尾(即 last)。它表示算法处理完成的输入位置,通常等于输入的结束迭代器。
out
类型为输出迭代器 O,指向输出范围中最后一个被复制元素的下一个位置。可以通过 out 迭代器继续向输出范围写入其他数据。
示例 2
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst;
dst.reserve(src.size() + 1);
dst[src.size()] = 10;
// 调用 reverse_copy 并获取返回值
auto result = std::ranges::reverse_copy(src, dst.begin());
// 输出输入范围和输出范围的信息
std::cout << "输入范围是否处理完毕?"
<< (result.in == src.end() ? "是" : "否")
<< std::endl; // 输出:是
std::cout << "输出范围的大小: " << dst.size() << std::endl; // 输出:5
//这里由于dst多一个空间,out指向了dst[5]的位置,即复制完元素的下一个位置。
std::cout << "输出结束迭代器指向的位置: " << *result.out << std::endl; // 输出:10
}
std::ranges::replace_copy_if
C++20 引入的算法,用于将范围中的元素复制到目标范围,并在复制过程中将所有满足特定条件的元素替换为另一个值。它是 std::replace_copy_if
的范围版本,支持范围操作和更现代的 C++ 风格。
功能
-
遍历输入范围
r
,将所有满足谓词pred
的元素替换为new_value
,并将结果复制到目标范围。 -
输入范围不会被修改,结果存储在目标范围中。
template< std::input_iterator I, std::sentinel_for<I> S, class T, std::output_iterator<const T&> O, | (since C++20) (until C++26) | |
template< std::input_iterator I, std::sentinel_for<I> S, class O, class T = std::iter_value_t<O> | (since C++26) | |
(4) | ||
template< ranges::input_range R, class T, std::output_iterator<const T&> O, | (since C++20) (until C++26) | |
template< ranges::input_range R, class O, class T = std::iter_value_t<O> | (since C++26) |
-
参数:
-
r
: 输入范围,可以是任何满足ranges::input_range
的范围(如容器、数组等)。 -
result
: 目标范围的起始迭代器,用于存储复制后的结果。 -
pred
: 一元谓词(函数或可调用对象),用于判断是否需要替换元素。如果pred(e)
返回true
,则元素e
会被替换为new_value
。 -
new_value
: 替换后的新值。
-
-
返回值: 返回目标范围的结束迭代器(即最后一个被复制元素的下一个位置)。
示例:
#include <iostream>
#include <vector>
#include <algorithm> // std::ranges::replace_copy_if
#include <ranges> // C++20 范围库
int main() {
// 示例 1: 替换 vector 中所有偶数元素为 -1,并复制到另一个 vector
std::vector<int> src = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> dst(src.size()); // 目标范围,大小与源范围相同
// 将所有偶数替换为 -1,并复制到 dst
auto end = std::ranges::replace_copy_if(
src, dst.begin(), [](int x) { return x % 2 == 0; }, -1);
// 输出结果
std::cout << "Source after replace_copy_if: ";
for (int i : src) {
std::cout << i << " ";
}
std::cout << "\n";
std::cout << "Destination after replace_copy_if: ";
for (auto it = dst.begin(); it != end.out; ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
// 示例 2: 替换数组中所有大于 10 的元素为 0,并复制到另一个数组
int src_arr[] = {5, 12, 8, 15, 3, 20};
int dst_arr[6]; // 目标数组,大小与源数组相同
// 将所有大于 10 的元素替换为 0,并复制到 dst_arr
auto end_arr = std::ranges::replace_copy_if(
src_arr, dst_arr, [](int x) { return x > 10; }, 0);
// 输出结果
std::cout << "Source array after replace_copy_if: ";
for (int i : src_arr) {
std::cout << i << " ";
}
std::cout << "\n";
std::cout << "Destination array after replace_copy_if: ";
for (auto it = std::begin(dst_arr); it != end_arr.out; ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
return 0;
}
输出:
Source after replace_copy_if: 1 2 3 4 5 6 7 8 9
Destination after replace_copy_if: 1 -1 3 -1 5 -1 7 -1 9
Source array after replace_copy_if: 5 12 8 15 3 20
Destination array after replace_copy_if: 5 0 8 0 3 0