概述
【STL】for_each()算法
一、for_each()概述
- for_each()算法非常灵活,允许你以不同的方式访问、处理、修改每一个元素
- 因此,for_each()既属于非更易型算法,又属于更易型算法
- 备注:自C++11起,range-based for循环提供了更方便更自然的行为。因此,for_each()可能逐渐降低其重要性
二、for_each()语法
- 头文件:
<algorithm>
- 相关语法:
- 对区间[beg,end)中的每一个元素调用op(elem)
- 返回op(它已在算法内部被改动过)的一个拷贝(副本)。C++11起,op的返回值被移动
- op可以改动元素。然而,请参考与transform()之间的比较,后者具有相同能力,但行事稍有不同
- op的任何返回值都会被忽略
- 复杂度:线型。调用op()共numElems次
- for_each()的实现如下:
三、for_each()的非更易型使用案例
演示案例①
例如下面调用for_each打印vector中的每一个元素,其参数3传递的是一个lambda
:
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for_each(vec.begin(), vec.end(),
[](int elem) {std::cout << elem << " "; }
);
}
演示案例②
当然,你可以可以向参数3传递一个函数
用来打印元素:
void print(int elem)
{
std::cout << elem << " ";
}
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for_each(vec.begin(), vec.end(), print);
}
演示案例③
- 我们也可以为其传入一个函数对象
- 下面的参数3创建一个print临时对象op传递给for_each(),然后每次调用op(int elem)打印元素
class print
{
public:
void operator()(int elem)
{
std::cout << elem << " ";
}
};
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
//创建一个print临时对象传递给for_each()
for_each(vec.begin(), vec.end(), print());
}
演示案例④
C++11,起,你可以使用range-based for循环完成上面的功能
,且更加方便
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for(const auto & elem:vec)
{
std::cout << elem << " ";
}
}
四、for_each()的更易型使用案例
演示案例①
- 我们调用向for_each()算法的参数3传入一个lambda,lambda的参数为引用类型,那么每次传入给lambda的将会是vector的每个元素的引用,然后在lambda内部改变vector的元素:
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
//改变每个元素的值
for_each(vec.begin(), vec.end(),
[](int& elem) {elem += 10; }
);
//打印
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
}
演示案例②
- 如果我们还想让lambda每次运行时,让其每个元素的值加上第一个元素的值,那么可以在
lambda使用[=]形式
:
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
std::cout << std::endl;
for_each(vec.begin(), vec.end(),
[=](int& elem) {elem += *(vec.begin()); }
);
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
}
- 结果如下图所示:
- lambda的[]内使用的是=号,因此传入的是vec.begin()的拷贝
- 其中vec.begin()等于1,每次每个元素每次都加上1,最终的结果如下图所示
演示案例③
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
std::cout << std::endl;
for_each(vec.begin(), vec.end(),
[&](int& elem) {elem += *(vec.begin()); }
);
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
}
- 结果如下图所示:
- lambda的[]内使用的是&号,因此传入的是vec.begin()的引用
- 第一次for_each()之后,vec.begin()等于2,之后每个元素每次都加上2,最终的结果如下图所示
演示案例④
- 我们也可以为其传入一个函数对象给它
- 下面也是构造一个AddValue临时对象op给for_each(),但是由于AddValue的构造函数需要一个函数,因此给出一个数值构造临时对象。然后每次op(int &elem),将数值+=
template<typename T>
class AddValue
{
private:
T theValue;
public:
AddValue(const T& v) :theValue(v) {}
void operator()(T& elem)
{
elem += theValue;
}
};
int main()
{
std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
//构造一个AddValue临时对象给for_each()
for_each(vec.begin(), vec.end(), AddValue<int>(10));
for (const auto & elem : vec)
{
std::cout << elem << " ";
}
}
五、for_each()的返回值
- 通过for_each()的语法我们知道,for_each()的返回值为参数3的一个拷贝
演示案例
- 代码如下:
class MeanValue
{
private:
long num;
long sum;
public:
MeanValue() :num(0), sum(0) {}
void operator()(int elem)
{
num++;
sum += num;
}
operator double()
{
return static_cast<double>(sum) / static_cast<double>(num);
}
};
int main()
{
vector<int> coll{ 1,2,3,4,5,6,7,8 };
//返回一个MeanValue()对象的拷贝,但是由于MeanValue支持operator double,因此我们可以直接将MeanValue转换为一个double类型返回
double mv = for_each(coll.begin(), coll.end(), MeanValue());
std::cout << "mean value: " << mv;
}
-
代码解析:
- 下面我们创建一个临时MeanValue()对象给for_each(),那么每次for_each()运算的时候都会调用这个临时对象的operator()运算符,之后将MeanValue()临时对象返回
- 又因为MeanValue()类型定义了operator double(),因此我们可以将一个MeanValue()对象转换为一个double类型,因此直接用double数据作为for_each()的返回值接收者
-
结果如下所示:
-
这个演示案例在“函数对象”一文中也介绍过,稍有不同,但是原理一致:https://blog.csdn.net/qq_41453285/article/details/105486284
-
也可以使用lambda完成任务(详情见文章:https://blog.csdn.net/qq_41453285/article/details/105486309),并以by reference方式传递返回值。然而在这种情形下lambda不见得比较好,因为function object不但封装sum作为其内部状态,也封装了“sum除以元素个数”这一最终触发
最后
以上就是明亮西装为你收集整理的【STL】for_each()算法【STL】for_each()算法的全部内容,希望文章能够帮你解决【STL】for_each()算法【STL】for_each()算法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复