博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 11 lambda
阅读量:6160 次
发布时间:2019-06-21

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

转载:http://www.cnblogs.com/kedebug/p/3224561.html

lambda 表达式的简单语法如下:[capture] (parameters) -> return value { body }

1、最简单的例子:

#include 
using namespace std; int main() { auto func = [] () { cout << "Hello world"; }; func(); }

上 面的 lambda 表达式 func 没有传入任何参数,也没有返回值,甚至我们可以对其简写成:auto func = [] { cout << "Hello world"; } 。并且配合 C++11标准加入的 auto 自动类型判断,省去了以前定义函数指针冗杂繁琐的过程,程序看上去如何优雅、简洁。

2、更加深入的示范:

假设我们有一个存放书籍地址的类,需要传入一个“搜索满足条件地址”的函数,并且将类定义成如下模样:

class AddressBook{public: template
std::vector
findMatchingAddresses (Func func) { std::vector
results; for ( auto itr = _addresses.begin(), end = _addresses.end(); itr != end; ++itr ) { if ( func( *itr ) ) { results.push_back( *itr ); } } return results; } private: std::vector
_addresses; };

类 AddressBook 封装了 findMatchingAddresses 函数,返回满足我们需要的书目,下面我们看看 lambda 表达式如何实现这一过程:

AddressBook global_address_book;vector
findAddressesFromOrgs () { return global_address_book.findMatchingAddresses( [] (const string& addr) { return addr.find( ".org" ) != string::npos; } ); }

上 面函数返回满足地址中带有 ".org" 字样的书籍条目,lambda 表达式虽然没有定义返回类型,但是编译器可以根据我们的 return 语句自动判断返回值是 boolean 类型。我们的 lambda 表达式中 [] 并没有 capture 任何变量,再下面的例子中将展示 [&] :

string name;cin >> name; return global_address_book.findMatchingAddresses( [&] (const string& addr) { return addr.find( name ) != string::npos; } );

再 次注意到,类 global_address_book 竟然能够访问到我们定义的局部变量 name 字符串,这正是 lambda 表达式的强大之处,[&] 代表 lambda body 中用到的变量都以“reference”的方式使用,还有更多的 capture 用法这里就不再叙述,有兴趣进一步了解的同学可以自行搜索。

3、Lambda 表达式使 STL 更加强大:

传统的情况下,我们会用下面的方式去访问容器里面的数据:

vector
v;v.push_back( 1 );v.push_back( 2 );//...for ( auto itr = v.begin(), end = v.end(); itr != end; itr++ ){ cout << *itr;}

但是当我们有了 Lambda 之后,利用 STL 里面的 for_each ,将会变成下面的代码:

vector
v;v.push_back( 1 );v.push_back( 2 );//...for_each( v.begin(), v.end(), [] (int val){ cout << val;});

你可能会想,上面的 for_each 循环,会不会使我们的程序有性能上的损耗?答案是否定的:for_each 的效率和迭代的效率是一致的,甚至加上 Lambda 之后,for_each 会利用 "loop unrolling" 机制使程序运行的更快。

Lambda 的引入给我们带来了一种全新的编程体验,它可以让我们把 "function" 当做是 "data" 一样传递,并且使我们从繁琐的语法中解放出来,更加关注于 "算法" 本身。我们也称 Lambda 为 Closure(闭包),顾名思义,这使我们的函数变得更加私有,所以限制了别人的访问,同时我们也可以更加方便的编程。

4、Lambda 与 资源管理:

前面在我的 「」一文中提到,智能指针可以利用 C++ 的 RAII(Resource acquisition is initialization) 特性,在类型(class)的析构函数时来完成自动释放指针所指向对象的目的。同样,在 Lambda 中,又把 RAII 这一特性体现的淋漓尽致:

class ScopeGuard{public:    explicit ScopeGuard(std::function
onExitScope) : onExitScope_(onExitScope) { } ~ScopeGuard() { onExitScope_(); }private: std::function
onExitScope_;private: // noncopyable ScopeGuard(ScopeGuard const&); ScopeGuard& operator=(ScopeGuard const&);};
int main() { HANDLE h = CreateFile(...); ScopeGuard onExit([&] { CloseHandle(h); }); ... return 0; }

看到上面的代码,我已经被 C++11 引入 Lambda 之后所带来的强大功能所折服了。我们不必担心何时去释放资源,并且连释放资源的方式「如 CloseHandle(h)」也与我们的代码紧密的融合在了一起,这将是十分美妙的一件事情。

5、Lambda 到底是什么类型:

auto func = [] () { cout << "hello world"; }; std::function
func = [] () { cout << "hello world"; }; auto func = [] (int val) { cout << val; return false; }; std::function
func = [] (int val) { cout << val; return false; };

 上面的上下 2 行代码效果是等效的,看到这里是否有种似曾相识的感觉?那 Lambda 和 我们定义的函数指针有什么区别呢:

typedef int (*func)();func f = [] () -> int { return 2; };f();

没错,这段代码是可以正常运行的,因为 Lambda 表达式中并没有 capture 任何本地变量,因此会被编译成普通的函数指针。最后采用 coolshell 里面 Lambda 的 2 点总结: 1)可以定义匿名函数,2)编译器会把其转成函数对象。

转载于:https://www.cnblogs.com/imystr/p/3817820.html

你可能感兴趣的文章
我的友情链接
查看>>
在C#调用C++的DLL简析(二)—— 生成托管dll
查看>>
Linux macos 常用终端操作
查看>>
企业网络的管理思路
查看>>
Linux磁盘分区与挂载
查看>>
J2se学习笔记一
查看>>
DNS视图及日志系统
查看>>
老李分享:Android性能优化之内存泄漏 3
查看>>
mysql命令
查看>>
来自极客标签10款最新设计素材-系列七
查看>>
极客技术专题【009期】:web技术开发小技巧
查看>>
PHP 简单计算器代码实现
查看>>
正则表达式的知识普及
查看>>
docker使用笔记
查看>>
华为eNSP模拟器上实现FTP服务
查看>>
【全球AI人才排行榜】美国第一,中国仅排名第7
查看>>
微信小程序输入框input
查看>>
MySql字符串函数使用技巧
查看>>
Doc2Vec,Word2Vec文本相似度 初体验。
查看>>
系统ghost后变成一个盘了别的分区的文件怎么找回
查看>>