`
izuoyan
  • 浏览: 9219518 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

C++ is on the way 11: 函数对象和Lambda表达式

阅读更多

Author:gnuhpc
WebSite:blog.csdn.net/gnuhpc

在看《高效编程十八式》中的第一小节的时候介绍了函数对象方法和Lambda表达式,以便完成“如果需要对函数指针进行更加灵活的定制”。

假设任务判断奇偶数,为了达到数据封装,我们使用函数对象的方法:

#include 
#include 
#include 
using namespace std;
class Functor
{
public:
   // The constructor.
   explicit Functor(int& evenCount) 
      : _evenCount(evenCount)
   {
   }
   void operator()(int n)
   {
      cout << n;
      if (n % 2 == 0) 
      {
         cout << " is even " << endl;
         // Increment the counter.
         _evenCount++;
      }
      else 
      {
         cout << " is odd " << endl;
      }
   }
private:
   int& _evenCount; // the number of even variables in the vector
};
int main() 
{
   vector<int> v;
   for (int i = 0; i < 10; ++i) 
   {
      v.push_back(i);
   }
   int evenCount = 0;
   for_each(v.begin(), v.end(), Functor(evenCount));
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

我们使用了一个类,这个类的作用就是判断奇偶并且进行计数,在for_each循环中,我们将这个Functor作为一个函数对象传入,此时调用Functor的构造函数,创建一个临时对象,当作用于vector每一个成员时,重载的()运算符发挥作用,表现的像个函数指针。显然这种方法在增加灵活性的同时却十分费力的写了一个如此长的类。

同样的任务我们使用Lambda表达式再写一遍:

#include 
#include 
#include 
using namespace std;
int main() 
{
 
   vector<int> v;
   for (int i = 0; i < 10; ++i) 
   {
      v.push_back(i);
   }
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) 
      {
         cout << " is even " << endl;
         // Increment the counter.
         evenCount++;
      }
      else 
      {
         cout << " is odd " << endl;
      }
   });
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

在这里我们在for_each的传入函数部分使用lambda表达式写了一个类似于Java中的匿名函数的东西。整个程序显得自然顺畅。[]字段是lambda表达式的外部变量捕获规则字段,=表示按值访问,&表示按引用访问(这两个是定义默认捕获规则时使用,若指定单个变量的规则,则使用&在变量名前边表示引用,而按值则直接写变量名即可),若没有则不能访问任何外部变量。而()表示函数体的变量列表,这个与一般的函数没有什么区别。

1. Lambda表达式的语法:

以下边的这个例子来说明语法:

#include 
#include 
#include 
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main() 
{
   vector<int> v(elementCount, 1);
   int x = 1;
   int y = 1;
   generate_n(v.begin() + 2, elementCount - 2, [&, y]() mutable throw() -> int {
      
      // Generate current value.
      int n = x + y;
      // Update previous two values.
      x = y;
      y = n;
      return n;
   });
   // Print the contents of the vector.
   for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
   cout << endl;
   cout << x << " " << y << endl;
}

我们看到generate_n这个STL方法,在第三个参数位置上使用了Lambda表达式:

[&, y]() mutable throw() –> int{}

首先,如前所述,[ ]表示外部变量捕获规则字段,若是不带有变量名称的则定义的是整个表达式的默认的捕获规则,在这里是引用;若指明了某一个变量则表示这个变量是单独定义捕获规则的,这里的y就是单独定义为按值捕获。

第二个字段是( ),这是传入参数字段,类似于函数,只是它不能有默认参数、不能有变长参数列表,必须有变量名。这个字段是可选字段。

第三个字段是mutable字段,若设置为mutable则按值捕获的外部变量的副本在表达式内可以被修改,否则会出现read only的错误。这个字段可选。

第四个字段是throw字段,限定能够抛出哪些异常。这个字段可选。

第五个字段是->字段,表示的返回参数类型。若只有一个返回语句的话,也可以省略这个字段,由编译器自行判断,虽然并不建议这么做。当然,若没有返回值就直接省略这个字段。

注:g++的编译方式为g++-4.5 以上,加上--std=c++0x标识

最后我们再写一个例子:

#include 
#include 
#include 
int main()
{
   using namespace std;
   // Create a list of integers with a few initial elements.
   list<int> numbers;
   numbers.push_back(13);
   numbers.push_back(17);
   numbers.push_back(42);
   numbers.push_back(46);
   numbers.push_back(99);
   // Use the find_if function and a lambda expression to find the 
   // first even number in the list.
   const list<int>::const_iterator result =
      find_if(numbers.begin(), numbers.end(),
         [](int n) { return (n % 2) == 0; });
   // Print the result.
   if (result != numbers.end())
   {
       cout << "The first even number in the list is " 
            << (*result) 
            << "." 
            << endl;
   }
   else
   {
       cout << "The list contains no even numbers." 
            << endl;
   }
}

参考文献:

分享到:
评论

相关推荐

    C++ 11 lambda 表达式

    C++ 11引入了lambda表达式,这是一个强大的特性,极大地增强了C++的函数式编程能力。Lambda表达式允许在程序中直接定义匿名函数,并且可以直接在需要的地方使用,无需预先声明。这对于处理回调函数、简化算法实现...

    C++ 中的 Lambda 表达式

    Lambda表达式是C++11的一个强大特性,它简化了匿名函数对象的创建过程。通过Lambda表达式,开发人员可以在代码的任何位置轻松定义函数对象,而不必为每个简单的功能定义独立的函数。此外,Lambda表达式还提供了灵活...

    C++11新特性:Lambda表达式.pdf

    C++11新特性:Lambda表达式 Lambda表达式是C++11新特性中的一种,全新的特性听起来很深奥,但却是很多其他语言早已提供(比如C#)或者即将提供(比如Java)的。Lambda表达式就是用于创建匿名函数的,GCC 4.5.x和...

    Java的lambda表达式讲解代码(各种lambda表达式使用方式:无参、一个参数、多参数、简化形式...)

    适用人群 本源码资源适用于具备一定Java编程基础的开发人员和学习者。...2、函数式接口与Lambda表达式:学习如何使用Lambda表达式与不同类型的函数式接口进行交互,并了解如何通过Lambda表达式实现函数的传递和组合

    Lambda表达式

    Lambda 表达式是一种匿名函数,可以包含表达式和语句,并且可用于创建委托或表达式树类型。所有 Lambda 表达式都使用 Lambda 运算符 =&gt;。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。 ...

    Python3中`sorted()函数`与`lambda表达式`原理解析

    博主的原文:lambda表达式sorted()函数目录:Python3中`sorted()函数`与`lambda表达式`原理解析问题描述原理解析附:原文基础知识lambda表达式sorted 函数问题描述很多小伙伴面对这样的排序,很是懵逼:# 预按照每个...

    Java 8 lambda表达式

    总之,Java 8的Lambda表达式极大地提升了代码的简洁性和可读性,特别是对于那些需要频繁使用回调函数或处理数据流的场景。通过将函数作为一个对象来传递,Java 8引入了函数式编程的概念,让开发者能以更加优雅的方式...

    lambda表达式和递归算法

    lambda 表达式和递归算法 lambda 表达式是一种匿名函数,可以用来定义小的、单次使用的函数。它通常用于数据处理、事件处理和其他需要临时函数的情况。lambda 表达式的基本语法是:`lambda arguments : expression`...

    C++ Lambda表达式详解

    C++ Lambda表达式是C++语言的一个重要特性,引入于C++11标准中。它可以作为函数对象使用,可以用来替代一些繁琐的函数声明和定义。Lambda表达式的基本语法结构如下:[capture list] (parameter list) specifiers ...

    Python匿名函数(lambda表达式)

    函数名 = lambda 参数 : 参数表达式 在使用的时候 函数名(变量) eg. 通过常规方式定义函数 if x&lt;y: res = x+y else: res = x-y return res print(fun(1,3)) # 4 通过lambda表达式定义一个函数 fun = ...

    C#中的Lambda表达式:简化委托与表达式树

    在C#编程语言中,Lambda表达式提供了一种简洁的方式来表示匿名函数,即没有具体名称的函数。Lambda表达式在C# 3.0中引入,作为.NET Framework的一部分,它们在LINQ(Language Integrated Query)查询中尤其有用,但...

    C#lambda表达式的使用

    Lambda 表达式是一个包含若干表达式和语句的匿名函数。可以被用作创建委托对象或表达式树类型。所有的 Lambda 表达式都使用操作符“=&gt;”,表示“goes to (转变为)”。操作符左边部分是输入参数表,右边部分是表达式...

    2_Lambda表达式.zip

    Lambda表达式是Java编程语言中的一个关键特性,自Java 8开始引入,它极大地简化了函数式编程,尤其是在处理集合数据时。Lambda表达式的主要目的是为了创建匿名函数,即没有名字的函数,它可以被当作一个值传递给方法...

    Java8的lambda表达式

    Java8的Lambda表达式是Java语言的一次重大更新,它引入了函数式编程的概念,极大地简化了处理匿名函数的方式,特别是在处理集合和并发操作时。Lambda表达式使得代码更加简洁、易读,同时也提升了程序的执行效率。在...

    java8 lambda表达式学习总结

    4. **构造器引用**:同样,Lambda 表达式可以用于创建对象,特别是当构造函数没有参数时,如 `list.add(() -&gt; new Thread())`。 5. **并行流**:Stream API 支持并行操作,通过 `.parallelStream()`,Lambda 表达式...

    精通lambda表达式: java多核编程

    函数式编程强调无副作用和纯函数,Lambda表达式是这一思想在Java中的体现。通过避免对状态的修改,可以更容易地理解和测试代码,同时减少并发编程中的错误来源。 6. **方法引用和构造器引用** Lambda表达式还可以...

    Lambda表达式测试demo

    Lambda表达式是Java 8引入的一种新特性,它极大地简化了函数式编程,使得代码更加简洁、易读。Lambda表达式本质上是匿名函数,可以理解为没有名字的函数,但功能与普通方法相同,能够被赋值给变量,也可以作为参数...

    Lambda表达式.pdf

    Lambda 表达式是匿名函数,可以包含表达式和语句,并且可用于创建委托或表达式树类型。所有 Lambda 表达式都使用 Lambda 运算符 =&gt; ,该运算符读为 “ goes to ”。该 Lambda 运算符的左边是输入参数(如果有),...

Global site tag (gtag.js) - Google Analytics