C++ function、bind以及lamda表达式

发表于:2015-1-16 09:45

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Augusdi    来源:51Testing软件测试网采编

分享:
  3. lambda
  讲完了function和bind, 下面我们来看lambda。有python基础的朋友,相信对于lambda不会陌生。看到这里的朋友,请再回忆一下前面讲的closure的概念,lambda就是用来实现closure的东东。它的最大用途也是在回调函数,它和前面讲的function和bind有着千丝万缕的关系。下面我们先通过例子来看看lambda的庐山真面目:
vector< int> vec;
/// 1. simple lambda
auto it = std::find_if(vec.begin(), vec.end(), [](int i) { return i > 50; });
class A
{
public:
bool operator(int i) const { return i > 50; }
};
auto it = std::find_if(vec.begin(), vec.end(), A());
/// 2. lambda return syntax
std::function< int(int)> square = [](int i) -> int { return i * i; }
/// 3. lambda expr: capture of local variable
{
int min_val = 10;
int max_val = 1000;
auto it = std::find_if(vec.begin(), vec.end(), [=](int i) {
return i > min_val && i < max_val;
});
auto it = std::find_if(vec.begin(), vec.end(), [&](int i) {
return i > min_val && i < max_val;
});
auto it = std::find_if(vec.begin(), vec.end(), [=, &max_value](int i) {
return i > min_val && i < max_val;
});
}
/// 4. lambda expr: capture of class member
class A
{
public:
void DoSomething();
private:
std::vector<int>  m_vec;
int               m_min_val;
int               m_max_va;
};
/// 4.1 capture member by this
void A::DoSomething()
{
auto it = std::find_if(m_vec.begin(), m_vec.end(), [this](int i){
return i > m_min_val && i < m_max_val; });
}
/// 4.2 capture member by default pass-by-value
void A::DoSomething()
{
auto it = std::find_if(m_vec.begin(), m_vec.end(), [=](int i){
return i > m_min_val && i < m_max_val; });
}
/// 4.3 capture member by default pass-by-reference
void A::DoSomething()
{
auto it = std::find_if(m_vec.begin(), m_vec.end(), [&](int i){
return i > m_min_val && i < m_max_val; });
}
  上面的例子基本覆盖到了lambda表达的基本用法。我们一个个来分析每个例子(标号与上面代码注释中1,2,3,4一致):
  (1)这是最简单的lambda表达式,可以认为用了lambda表达式的find_if和下面使用了functor的find_if是等价的
  (2)这个是有返回值的lambda表达式,返回值的语法如上面所示,通过->写在参数列表的括号后面。返回值在下面的情况下是可以省略的:
  a. 返回值是void的时候
  b. lambda表达式的body中有return expr,且expr的类型与返回值的一样
  (3)这个是lambda表达式capture本地局部变量的例子,这里三个小例子,分别是capture时不同的语法,第一个小例子中=表示capture的变量pass-by-value, 第二个小拿出中&表示capture的变量pass-by-reference,第三个小例子是说指定了default的pass-by-value, 但是max_value这个单独pass-by-reference
  (4)这个是lambda表达式capture类成员变量的例子,这里也有三个小例子。第一个小例子是通过this指针来capture成员变量,第二、三个是通过缺省的方式,只不过第二个是通过pass-by-value的方式,第三个是通过pass-by-reference的
  分析完了上面的例子,我们来总结一下关于lambda表达式使用时的一些注意事项:
  (1)lambda表达式要使用引用变量,需要遵守下面的原则:
  a. 在调用上下文中的局部变量,只有capture了才可以引用(如上面的例子3所示)
  b. 非本地局部变量可以直接引用
  (2)使用者需要注意,closure(lambda表达式生成的可调用实体)引用的变量(主要是指针和引用),在closure调用完成之前,必须保证可用,这一点和上面bind绑定参数之后生成的可调用实体是一致的
  (3)关于lambda的用处,就是用来生成closure,而closure也是一种可调用实体,所以可以通过std::function对象来保存生成的closure,也可以直接用auto
  通过上面的介绍,我们基本了解了function, bind和lambda的用法,把三者结合起来,C++将会变得非常强大,有点函数式编程的味道了。最后,这里再补充一点,对于用bind来生成function和用lambda表达式来生成function, 通常情况下两种都是ok的,但是在参数多的时候,bind要传入很多的std::placeholders,而且看着没有lambda表达式直观,所以通常建议优先考虑使用lambda表达式。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号