使用初始化捕获来把对象移动到闭包
2017-08-29 15:25
274 查看
有时候,你想要的既不是值捕获,也不是引用捕获。如果你想要把一个只可移动对象(例如,std::unique_ptr或std::future类型对象)放入闭包中,C++11没有办法做这事。如果你有个对象的拷贝操作昂贵,但移动操作廉价(例如,大部分的标准容器),然后你需要把这个对象放入闭包中,那么比起拷贝这个对象你更愿意移动它。但是,C++11还是没有办法完成这事。
但那是C++11,C++14就不一样啦,它直接支持将对象移动到闭包。如果你的编译器支持C++14,欢呼吧,然后继续读下去。如果你依然使用C++11的编译器,你还是应该欢呼和继续读下去,因为C++11有接近移动捕获行为的办法。
缺少移动捕获被认为是C++11的一个缺陷,最直接的补救方法是在C++14中加上它,但标准委员会采用了另外一种方法。它们提出了一种新的、十分灵活的捕获技术,引用捕获只是属于这种技术的其中一种把戏。这种新能力被称为初始化捕获(init capture),实际上,它可以做C++11捕获格式能做的所有事情,而且更多。初始化捕获不能表示的是默认捕获模式,不过条款31解释过无论如何你都应该远离默认捕获模式。(对于将C++11捕获转换为初始化捕获的情况,初始化捕获的语法会比较啰嗦,所以如果C++11捕获能解决问题的情况下,最好使用C++11捕获。)
使用初始化捕获让你有可能指定
成员变量的名字(留意,这是闭包类的成员变量,这个闭包类由lambda生成)和 (初始化那成员变量的)表达式 。
这里是如何使用初始化捕获来把std::unique_ptr移动到闭包内:
?
初始化捕获的代码部分是
[code]这应该清楚地表明在C++14中,C++11的“捕获”概念得到显著推广,因为在C++11,不可能捕获一个表达式的结果。因此,初始化捕获的另一个名字是generalized lambda capture(广义lambda捕获?)。
但那是C++11,C++14就不一样啦,它直接支持将对象移动到闭包。如果你的编译器支持C++14,欢呼吧,然后继续读下去。如果你依然使用C++11的编译器,你还是应该欢呼和继续读下去,因为C++11有接近移动捕获行为的办法。
缺少移动捕获被认为是C++11的一个缺陷,最直接的补救方法是在C++14中加上它,但标准委员会采用了另外一种方法。它们提出了一种新的、十分灵活的捕获技术,引用捕获只是属于这种技术的其中一种把戏。这种新能力被称为初始化捕获(init capture),实际上,它可以做C++11捕获格式能做的所有事情,而且更多。初始化捕获不能表示的是默认捕获模式,不过条款31解释过无论如何你都应该远离默认捕获模式。(对于将C++11捕获转换为初始化捕获的情况,初始化捕获的语法会比较啰嗦,所以如果C++11捕获能解决问题的情况下,最好使用C++11捕获。)
使用初始化捕获让你有可能指定
成员变量的名字(留意,这是闭包类的成员变量,这个闭包类由lambda生成)和 (初始化那成员变量的)表达式 。
这里是如何使用初始化捕获来把std::unique_ptr移动到闭包内:
?
pw = std::move(pw),“=”左边的是你指定的闭包类的成员变量名,右边的是进行初始化表达式。有趣的是,“=”左边的作用域和右边的作用域不同,左边的作用域是在闭包类内,而右边的作用域和lambda被定义的地方的作用域相同。在上面的例子中,“=”左边的名字pw指的是闭包类的成员变量,而右边的名字pw指的是在lambda之前声明的对象,即由make_unique创建的对象。所以
pw = std::move(pw)的意思是:在闭包中创建一个成员变量pw,然后用——对局部变量pw使用std::move的——结果初始化那个成员变量。
通常,lambda体内代码的作用域在闭包类内,所以代码中的
pw指的是闭包类的成员变量。
在上面例子中,注释“配置*pw”表明了在std::make_unique创建Widget之后,在lambda捕获指向Widget的std::unique_ptr之前,Widget在某些方面会被修改。如果这个配置不是必需的,即,如果std::make_unique创建的Widget对象的状态已经适合被lambda捕获,那么局部变量
pw是不必要的,因为闭包类的成员变量可以直接被std::make_unique初始化:
?
相关文章推荐
- Effective Modern C++ 条款32 对于lambda,使用初始化捕获来把对象移动到闭包
- 使用数组来初始化 vector 对象
- java中类/对象的初始化顺序以及静态代码块的使用
- non-aggregates(非聚合)对象不能使用初始化列表
- 确定对象在被使用前被初始化(Make sure that objects are initialized before they’re used)——effective c++学习笔记
- 课程设计__类和对象的简单使用(构造函数初始化)
- Unity3d修炼之路:GUI按钮简单使用,完成对一个简单对象Cube的移动,旋转
- 条款4:确定对象被使用前已被初始化(Make sure that objects are initialized before they're used)
- java中类/对象的初始化顺序以及静态代码块的使用
- Effective C++ Item 4 确定对象被使用前已先被初始化
- effective c++条款04确定对象使用前已经被初始化
- 读书笔记_Effective_C++_条款四:确定对象被使用前已先被初始化
- 深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解
- Effective C++条款04解读:确定对象被使用之前已先被初始化
- c# 使用初始化器初始化对象
- unity 使用角色控制器CharacterController移动对象造成模型动画的抖动
- Map生成器 map适配器现在可以使用各种不同的Generator,iterator和常量值的组合来填充Map初始化对象
- [EC++_item4]确定对象被使用前已先被初始化
- 确定对象在被使用前被初始化(Make sure that objects are initialized before they’re used)——effective c++学习笔记
- 《Effect C++》学习------条款04:确定对象被使用前以先被初始化