考虑到它的能力,它的使用出奇地简单。
如何做到这一点…
在这个食谱中,我们将探索 std::transform() 函数的几个应用:

我们首先定义一个简单的函数来打印容器的内容:
void printc(auto& c, string_view s = "") { if(s.size()) cout << format("{}: ", s); for(auto e : c) cout << format("{} ", e); cout << '\n';}

我们将使用这个来查看我们的转换结果。
在 main() 函数中,让我们声明几个向量:
int main() { vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; vector<int> v2; printc(v1, "v1"); ...}
这打印出 v1 的内容:
v1: 1 2 3 4 5 6 7 8 9 10
现在我们可以使用 transform() 函数将每个值的平方插入到 v2 中:
cout << "squares:\n";transform(v1.begin(), v1.end(), back_inserter(v2), [](int x){ return x x; });printc(v2, "v2");
transform() 函数接受四个参数。前两个是源范围的 begin() 和 end() 迭代器。第三个参数是目标范围的 begin() 迭代器。在这种情况下,我们使用 back_inserter() 算法在 v2 中插入结果。第四个参数是转换函数。在这种情况下,我们使用一个简单的 lambda 来平方值。
输出:
squares:v2: 1 4 9 16 25 36 49 64 81 100
当然,我们可以使用 transform() 与任何类型。这里有一个将字符串对象向量转换为小写的示例。首先,我们需要一个函数来返回字符串的小写值:
string str_lower(const string& s) { string outstr{}; for(const char& c : s) { outstr += tolower(c); } return outstr;}
现在我们可以使用 str_lower() 函数与 transform():
vector<string> vstr1{"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" };vector<string> vstr2;printc(vstr1, "vstr1");cout << "str_lower:\n";transform(vstr1.begin(), vstr1.end(), back_inserter(vstr2), [](string& x){ return str_lower(x); });printc(vstr2, "vstr2");
这对于 vstr1 中的每个元素调用 str_lower() 并将结果插入到 vstr2 中。结果是:
vstr: Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune Plutostr_lower:vstr: mercury venus earth mars jupiter saturn uranus neptune pluto
(是的,冥王星对我来说永远是一颗行星。)
还有一个 ranges 版本的 transform:
cout << "ranges squares:\n";auto view1 = views::transform(v1, [](int x){ return x x;});printc(view1, "view1");
ranges 版本有一个更简洁的语法,并且返回一个视图对象,而不是填充另一个容器。
它是如何工作的…
std::transform() 函数的工作方式非常类似于 std::copy(),只是增加了用户提供的函数。输入范围中的每个元素都传递给函数,函数的返回值被复制赋值到目标迭代器。这使 transform() 成为一个非常有用和强大的算法。
值得注意的是,transform() 不保证元素将按顺序处理。如果您需要确保转换的顺序,您将希望使用 for 循环:
v2.clear();// 重置向量 v2 为空状态for(auto e : v1) v2.push_back(e e);printc(v2, "v2");
输出:
v2: 1 4 9 16 25 36 49 64 81 100