深入理解lambda表达式
#include "stdafx.h" #include <memory> #include <iostream> #include <functional> class AObject //: public std::enable_shared_from_this<AObject> { public: AObject() : m_i(0) { std::cout << "AObject construct" << std::endl; } virtual ~AObject() { std::cout << "AObject distruct" << std::endl; } void test() { if (m_callback){ m_callback(); } } template<typename F> void setCallback(F f) { m_callback = f; } private: int m_i; std::function<void()> m_callback; }; int _tmain(int argc, TCHAR* argv[]) { std::shared_ptr<AObject> pAObject(new AObject()); std::cout << "after constructing count is " << pAObject.use_count() << std::endl; pAObject->setCallback( //[&pAObject](){ [pAObject](){ std::cout << "in callback count is " << pAObject.use_count() << std::endl; //pAObject->~AObject();//你传值进来的共享指针,需要自行调用析构 } ); std::cout << "after setting callback count is " << pAObject.use_count() << std::endl; int ii; for (ii = 0; ii < 5;ii++){ pAObject->test(); } return 0; }
输出的结果是:
AObject construct
after constructing count is 1
after setting callback count is 2
in callback count is 2
in callback count is 2
in callback count is 2
in callback count is 2
in callback count is 2
如果解开
//[&pAObject](){
这行的注释,并注释掉下一行
[pAObject](){
执行的结果是
AObject construct
after constructing count is 1
after setting callback count is 1
in callback count is 1
in callback count is 1
in callback count is 1
in callback count is 1
in callback count is 1
AObject distruct
结论
1. lambda表达式的闭包列表中的变量如果是传值的,确实是传值的,如果将共享指针放入闭包列表,会使共享指针引用计数加1。
2. lambda表达式类似定义了一个类,闭包列表中的变量,类似这个类中的静态变量,定义之后被初始化,只初始化一次。
3. lambda表达式每次执行,类似实例化了一个对象,把函数体作为构造函数执行,构造函数的参数列表就是lambda表达式的参数列表就是。
4. lambda表达式设置好了就一直存在,你看第一种情况下程序都退出了,还是没有释放AObject对象。你需要自行减少引用计数,方法是调用一下析构函数。
你可以将
//[&pAObject](){
这行继续注释掉,并放开
[pAObject](){
和
// pAOjbect->~AObject();
这2行的注释,执行结果是
AObject construct
after constructing count is 1
after setting callback count is 2
in callback count is 2
AObject distruct
AObject distruct
最后2行,第一行是手动执行析构,而打印出第一句,而第二句是程序结束时,因为引用计数为0,自动释放对象,而打印出来的。
很有意思,std::asio代码的例子程序c++11版本的,你深入进去找,它就是这么干的。