Lambda 捕获列表:如果不捕获整个对象,就不可能按值捕获对象的成员字段?
Lambda capture list: capturing object's member field by value not possible without capturing the whole object?
以下代码
void CMainWindow::someMethod(const CLocationsCollection& parentItem)
{
auto f = [this, parentItem.displayName](){};
}
给我一个错误:
错误C2143:语法错误:'.'之前缺少']'
如果我想通过ref捕获parentItem.displayName
,我将为它创建一个非依赖的别名标识符:
const QString& name = parentItem.displayName;
auto f = [this, &name](){}; // Or should it be [this, name] ?
但是我需要按值捕获它,我不想捕获整个parentItem
,因为它很重。有解决方案吗?
p。捕获列表中的名称必须是标识符。是不是parentItem.displayName
(作为一个整体)一个标识符?为什么它不能被编译器正确解析?
注释:本文中的所有标准参考均取自c++标准草案n3337。
介绍
标准规定捕获必须是&
, =
, this
, 标识符,或者标识符前面是&
。
5.1.2
Lambda表达式[expr.prim.lambda]
capture-list: capture ..._opt capture-list , capture ..._opt capture: identifier & identifier this
由于parentItem.displayName
不是标识符,而是"类成员访问表达式"。当编译器拒绝你的代码片段时是正确的。
5.2.5p1
类成员访问[expr.ref]
后缀表达式后跟点
.
或箭头->
,可选后跟关键字template
(14.2),然后后跟id-expression,是一个后缀表达式。66该求值的结果与id-expression一起决定整个后缀表达式的结果。
如果有一种方法可以用表达式初始化捕获就好了…
在 c++ 14中,将能够使用init-capture来规避手头的问题,如下面的代码片段所示。它将创建一个名称为display_name的捕获,并使用parentItem.displayName的值进行初始化。
[display_name = parentItem.displayName](){ ... };
那么 c++ 11呢?
遗憾的是,在 c++ 11中没有这样的功能。因此,该问题的解决方案是对数据成员创建一个本地引用,然后在创建lambda时捕获该引用。auto& lmb_display_name = parentItem.displayName;
[lmb_display_name](){ ... }; // the lambda will have a copy of `parentItem.displayName`
注释:您的原始帖子似乎暗示,在lambda的捕获列表中R的名称将使lambda包含对R引用的引用,这是不正确的,从这个代码片段可以看出。
相关文章:
- 指向设备对象成员的指针
- 访问由unique_ptr传递的对象成员
- 引用对象成员函数的成员函数
- 将 C# 对象(包含静态对象成员)作为参数传递给 C++/CLI 程序
- Lua C API - 从C++分配和使用类的对象成员
- Rapidjson 遍历并获取复杂 JSON 对象成员的值
- 类对象成员变量在调用函数时不会更改
- 对象成员变量还是继承
- C++多态性:有没有办法找到对象成员函数的地址?
- 重载对象成员的比较运算符
- 获取未初始化对象成员的地址是否定义良好?
- 在优先级队列被推送到队列后,如何编辑对象成员
- 为什么在这里调用析构函数,以及在调用该对象析构函数后如何调用对象成员函数?
- 通过 std::bind 从对象成员检索值
- 保留对象成员变量的本地副本
- 有没有办法为静态对象成员定义一个符合开关标准的常量?
- 没有默认构造函数的对象成员的 wig setter
- 对象成员数组C++默认初始化
- 如何在数组中添加对象成员
- 使用聚合创建和关联两个不同的对象成员