ben*_*der 52 c++ stl-algorithm c++11
两者都可用于将函数应用于一系列元素.
在高层次上:
std::for_each 忽略函数的返回值,并保证执行的顺序.std::transform 将返回值赋给迭代器,并不保证执行的顺序.你什么时候喜欢使用那个?有任何微妙的警告吗?
Ili*_*llo 51
std::transform是一样的map.我们的想法是将函数应用于两个迭代器之间的每个元素,并获得由应用此类函数产生的元素组成的不同容器.您可能希望将其用于,例如,将对象的数据成员投影到新容器中.在下文中,std::transform用于转换std::strings容器中的std::size_ts 容器.
std::vector<std::string> names = {"hi", "test", "foo"};
std::vector<std::size_t> name_sizes;
std::transform(names.begin(), names.end(), std::back_inserter(name_sizes), [](const std::string& name) { return name.size();});
Run Code Online (Sandbox Code Playgroud)
另一方面,您执行std::for_each唯一的副作用.换句话说,std::for_each非常类似于基于范围的普通for循环.
回到字符串示例:
std::for_each(name_sizes.begin(), name_sizes.end(), [](std::size_t name_size) {
std::cout << name_size << std::endl;
});
Run Code Online (Sandbox Code Playgroud)
实际上,从C++ 11开始,使用基于范围的for循环的terser表示法可以实现相同的目的:
for (std::size_t name_size: name_sizes) {
std::cout << name_size << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
Nia*_*all 22
您的高级概述
std::for_each忽略函数的返回值并保证执行顺序.std::transform将返回值赋给迭代器,并不保证执行的顺序.
几乎涵盖了它.
另一种看待它的方式(优先选择另一种方式);
还要记住的另一件事(微妙的警告)是std::transformC++ 11之前和之后操作要求的变化(来自en.cppreference.com);
基本上这些是允许未确定的执行顺序.
我何时使用一个而不是另一个?
如果我想操纵范围中的每个元素,那么我使用for_each.如果我必须从每个元素计算一些东西,那么我会使用transform.当使用for_each和时transform,我通常将它们与lambda配对.
也就是说,for_each自从forC++ 11(for (element : range))中基于范围的循环和lambdas 的出现以来,我发现我对传统的当前用法有所减少.我发现它的语法和实现非常自然(但你的里程数会有所不同),并且更适合某些用例.
Bug*_*tGG 13
虽然问题已得到解答,但我相信这个例子可以进一步澄清这一区别.
for_each属于非修改STL操作,这意味着这些操作不会更改集合的元素或集合本身.因此,for_each返回的值始终被忽略,并且不会分配给集合元素.尽管如此,仍然可以修改集合的元素,例如,当使用引用将元素传递给f函数时.人们应该避免这种行为,因为它与STL原则不一致.
相反,transform函数属于修改STL操作,并将给定谓词(unary_op或binary_op)应用于集合或集合的元素,并将结果存储在另一个集合中.
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
void printer(int i) {
cout << i << ", ";
}
int main() {
int mynumbers[] = { 1, 2, 3, 4 };
vector<int> v(mynumbers, mynumbers + 4);
for_each(v.begin(), v.end(), negate<int>());//no effect as returned value of UnaryFunction negate() is ignored.
for_each(v.begin(), v.end(), printer); //guarantees order
cout << endl;
transform(v.begin(), v.end(), v.begin(), negate<int>());//negates elements correctly
for_each(v.begin(), v.end(), printer);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
将打印:
1, 2, 3, 4,
-1, -2, -3, -4,
Run Code Online (Sandbox Code Playgroud)