博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初探C++11之lambda表达式
阅读量:4616 次
发布时间:2019-06-09

本文共 4619 字,大约阅读时间需要 15 分钟。

lambda表达式是函数式编程的基础。咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下。这里只是介绍C++11中的lambda表达式以及与此相关的闭包(closure)。

 

同样,这里首先给出参考文档

 

其次,给出两个例子,可以看出lambda表达式的写法

[](int x, int y) { return x + y; } [](int x, int y) -> int { int z = x + y; return z + x; }   //表明返回值类型是int型

也就是说,一个lambda表达式很类似于普通的函数定义的写法,区别在于三点,一是没有函数名(你也可以认为函数名是[]),二是这个函数没有普通函数那样的返回值类型,返回值类型的写法在第2行,即在参数列表与函数定义之间以箭头写明,三是在参数列表之前有一个[] (其实这里还可能有更多的形式,后面会说)

 

第三,lambda表达式的标准形式是什么?

如下。这里先只是列出,后面会详细解释。

lambda-expression:

  lambda-introducer lambda-declaratoropt compound-statement
lambda-introducer:
  [ lambda-captureopt ]

lambda-capture:

  capture-default
  capture-list
  capture-default , capture-list
capture-default:
  &
  =
capture-list:
  capture
  capture-list , capture
capture:
  identifier
  & identifier
  this
lambda-declarator:
  ( parameter-declaration-clause ) attribute-specifieropt mutableopt exception-specificationopt trailing-return-typeopt

第四,进一步的分析

上面的标准形式中,最不好理解的可能就是lambda-capture了。其实它对应的就是闭包的概念,而作用是描述外部传入的参数。

wiki上有一个例子,如下

std::vector
someList; int total = 0; std::for_each(someList.begin(), someList.end(), [&total](int x) {
total += x; }); std::cout << total;

这段代码做的事情是把someList中的所有变量求和。其中定义的lambda函数如下,

[&total](int x) {total += x;}

与前面的例子不同,这里的lambda-introducer是[&total]而不是之前的[]。这么写的作用是,在这个lambda函数中以引用方式使用外部变量total,这样求和结果就可以存放于这个变量中。那么类似的,还可以以传值方式使用外部变量,写成[total]就可以,而且,如果需要用到的外部变量较多,可以有简略的写法。一个完整的列表如下(来自wiki,这里我把他们翻译成我们比较习惯的表述形式)

[] // 没有定义任何变量。使用未定义变量会导致错误。 [x, &y] // x 以传值方式传入(默认),y 以引用方式传入。 [&] // 任何被使用到的外部变量皆隐式地以引用方式加以使用。 [=] // 任何被使用到的外部变量皆隐式地以传值方式加以使用。 [&, x] // x 显示地以传值方式加以使用。其余变量以引用方式加以使用。 [=, &z] // z 显示地以引用方式加以使用。其余变量以传值方式加以使用。

第五,代码练习及验证

接下来,我们自己写一些代码来做一些练习以及验证一些事情。以下代码在visual studio 2010下测试通过。

首先是模仿实例写一些代码。

#include 
#include
#include
void ShowVector(std::vector
& vecTest) {
std::for_each(vecTest.begin(), vecTest.end(), [](int x) {
std::cout<
<<' '; } ); std::cout<
vecTest(10,1); ShowVector(vecTest); std::for_each(vecTest.begin(), vecTest.end(), [](int& x) { x += 2; } ); ShowVector(vecTest); int iTotal = 0; std::for_each(vecTest.begin(), vecTest.end(), [&iTotal](int x) { iTotal += x; } ); std::cout << std::endl << iTotal << std::endl; iTotal = 0; std::for_each(vecTest.begin(), vecTest.end(), [&](int x) { iTotal += x; } ); std::cout << std::endl << iTotal << std::endl; //iTotal = 0; //std::for_each(vecTest.begin(), vecTest.end(), // [=](int x) // { // iTotal += x; // build error,error C3491: 'iTotal': a by-value capture cannot be modified in a non-mutable lambda // } //); //std::cout << std::endl << iTotal << std::endl; //iTotal = 0; //std::for_each(vecTest.begin(), vecTest.end(), // [iTotal](int x) // { // iTotal += x; // build error, error C3491: 'iTotal': a by-value capture cannot be modified in a non-mutable lambda // } //); //std::cout << std::endl << iTotal << std::endl; iTotal = 0; std::for_each(vecTest.begin(), vecTest.end(), [=, &iTotal](int x) { iTotal += x; } ); std::cout << std::endl << iTotal << std::endl; int iAdd = 1; std::for_each(vecTest.begin(), vecTest.end(), [=](int& x) { x += iAdd; } ); ShowVector(vecTest); std::for_each(vecTest.begin(), vecTest.end(), [iAdd](int& x) { x += iAdd; } ); ShowVector(vecTest); char e = 0; scanf_s("%c", &e, 1); return 0; }

运行结果如下,

1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 30 30 30 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5

这里值得注意的是其中的注释掉的代码,这里我们以传值方式使用外部变量,但是在lambda函数内部却试图修改该变量的值,其实这是没什么作用的,而visual studio直接给出报错,检查很仔细,不错。

 

那么我们再考虑一个问题,lambda表达式的运行效率?我们来试一下。测试机器双核4G内存。

#include "windows.h" #include 
#include
#include
void ModVal(int& iVal) {
iVal *= 3; } #define ARRAY_SIZE 10000000 int main() {
int m = 0; std::vector
vecTest(ARRAY_SIZE,0); std::for_each(vecTest.begin(), vecTest.end(), [&m](int& x) {
x = m++; } ); // test1 //std::for_each(vecTest.begin(), vecTest.end(), // [](int& x) // {
// x *= 3; // } //); // test2 //for (int i = 0; i < ARRAY_SIZE; i++) //{
// vecTest[i] *= 3; //} // test3 std::for_each(vecTest.begin(), vecTest.end(), ModVal); char e = 0; scanf_s("%c", &e, 1); return 0; }

分别对以上的test1, test2和test3使用QueryPerformanceFrequency()函数计时,我们可以得到如下的结果,

test1: 26.8ms

test2: 27.6ms

test3: 24.2ms

也就是说,最快的是test3,即不采用lambda表达式,而是直接用函数……多少有点出乎意料。而最慢的是直接用for循环的操作,不过它和用lambda表达式的结果很接近。

 

第六,其他

成员函数内部的lambda函数,lambda函数作为对象。留着后面写。

转载于:https://www.cnblogs.com/l00l/archive/2012/02/04/2338038.html

你可能感兴趣的文章
JAVA基础入门(JDK、eclipse下载安装)
查看>>
最基础的applet运用--在applet上画线
查看>>
并不对劲的hdu4777
查看>>
linux使用rz、sz快速上传、下载文件
查看>>
判断数字的正则表达式
查看>>
DOC常用命令(转)
查看>>
php写一个判断是否有cookie的脚本
查看>>
Mac配置Fiddler抓包工具
查看>>
转:Java并发集合
查看>>
Word截图PNG,并压缩图片大小
查看>>
Python项目对接CAS方案
查看>>
mysql产生随机数
查看>>
编程风格
查看>>
熟悉常用的Linux命令
查看>>
易之 - 我是个大师(2014年3月6日)
查看>>
Delphi中窗体的事件
查看>>
file_get_contents()获取https出现这个错误Unable to find the wrapper “https” – did
查看>>
linux vi编辑器
查看>>
js树形结构-----(BST)二叉树增删查
查看>>
contract
查看>>