std::transform
是 C++ 标准库中的一个算法,用于对容器(如数组、向量、字符串等)中的元素进行转换操作,并将结果存储到指定的目标位置。它可以对单个范围或两个范围的元素进行操作,并将结果写入另一个容器。
1. 头文件
使用 std::transform
需要包含头文件:
#include <algorithm>
2. 函数原型
std::transform
有两种重载形式:
形式 1:对单个范围进行操作
template <class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform(InputIterator first1, InputIterator last1,OutputIterator result, UnaryOperation op);
first1
和last1
:输入范围的起始和结束迭代器。result
:输出范围的起始迭代器。op
:一元操作函数,对输入范围的每个元素进行操作。
形式 2:对两个范围进行操作
template <class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation>
OutputIterator transform(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, OutputIterator result,BinaryOperation op);
first1
和last1
:第一个输入范围的起始和结束迭代器。first2
:第二个输入范围的起始迭代器。result
:输出范围的起始迭代器。op
:二元操作函数,对两个输入范围的对应元素进行操作。
3. 基本用法
示例 1:对单个范围进行操作
将字符串中的每个字符转换为大写:
#include <iostream>
#include <algorithm>
#include <string>int main() {std::string s = "hello";std::transform(s.begin(), s.end(), s.begin(), ::toupper);std::cout << s << std::endl; // 输出: HELLOreturn 0;
}
s.begin()
和s.end()
:输入范围的起始和结束迭代器。s.begin()
:输出范围的起始迭代器(原地修改)。::toupper
:一元操作函数,将字符转换为大写。
示例 2:对两个范围进行操作
将两个向量的对应元素相加:
#include <iostream>
#include <algorithm>
#include <vector>int main() {std::vector<int> v1 = {1, 2, 3};std::vector<int> v2 = {4, 5, 6};std::vector<int> result(v1.size());std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), std::plus<int>());for (const auto& elem : result) {std::cout << elem << " "; // 输出: 5 7 9}return 0;
}
v1.begin()
和v1.end()
:第一个输入范围的起始和结束迭代器。v2.begin()
:第二个输入范围的起始迭代器。result.begin()
:输出范围的起始迭代器。std::plus<int>()
:二元操作函数,将两个元素相加。
4. 自定义操作函数
示例 3:使用 Lambda 表达式
将向量中的每个元素平方:
#include <iostream>
#include <algorithm>
#include <vector>int main() {std::vector<int> v = {1, 2, 3};std::vector<int> result(v.size());std::transform(v.begin(), v.end(), result.begin(), [](int x) { return x * x; });for (const auto& elem : result) {std::cout << elem << " "; // 输出: 1 4 9}return 0;
}
[](int x) { return x * x; }
:Lambda 表达式,定义了一个一元操作函数。
示例 4:使用函数对象
将两个字符串的对应字符拼接:
#include <iostream>
#include <algorithm>
#include <string>struct Concat {std::string operator()(char a, char b) const {return std::string(1, a) + std::string(1, b);}
};int main() {std::string s1 = "abc";std::string s2 = "123";std::vector<std::string> result(s1.size());std::transform(s1.begin(), s1.end(), s2.begin(), result.begin(), Concat());for (const auto& elem : result) {std::cout << elem << " "; // 输出: a1 b2 c3}return 0;
}
Concat
:函数对象,定义了一个二元操作函数。
5. 注意事项
-
输出范围的大小:
- 输出范围必须足够大,以容纳转换后的结果。否则会导致未定义行为。
- 可以使用
std::back_inserter
将结果插入到动态容器中:std::vector<int> result; std::transform(v.begin(), v.end(), std::back_inserter(result), [](int x) { return x * x; });
-
原地修改:
- 如果输入范围和输出范围相同,
std::transform
会原地修改数据。
- 如果输入范围和输出范围相同,
-
性能:
std::transform
的时间复杂度为 O(n),其中 n 是输入范围的大小。
6. 总结
std::transform
主要特点包括:
- 支持对单个范围或两个范围的操作。
- 可以使用内置函数、Lambda 表达式或自定义函数对象作为操作函数。
- 可以原地修改数据,也可以将结果存储到另一个容器中。