【问题标题】:Capture a local pointer by value and the rest by reference in a lambda通过值捕获本地指针,其余的在 lambda 中通过引用捕获
【发布时间】:2018-08-12 20:36:41
【问题描述】:

我想在我的 lambda 表达式中捕获一个本地指针。目前我的代码是这样的

MYButton* button;
button->onPress = [index,&](control*){
            button->foobar(x, y);
    };

我得到了错误

错误:(835, 13) 变量 'button' 不能被隐式捕获 在没有指定捕获默认值的 lambda 中

我的印象是在捕获子句中使用& 意味着通过引用捕获本地范围内的所有内容。在那种情况下,为什么我会收到此错误?

【问题讨论】:

  • 如果您希望 lambda 函数修改它们并影响本地,或者如果它们的复制成本很高,您几乎只想通过引用捕获本地。当然,对于这样的指针,您更愿意按值捕获。

标签: c++11 lambda


【解决方案1】:

没有识别捕获默认值,因为捕获默认值必须是捕获中的第一项。详情请见cpp reference

正确的代码应该是

MYButton* button;
button->onPress = [&,index](control*){
            button->foobar(x, y);
    };

此外,似乎没有使用捕获index。您可以消除它,在这种情况下,代码将是

MYButton* button;
button->onPress = [&](control*){
            button->foobar(x, y);
    };

而且,正如 Chris Dodd 所提到的,这个 lambda 的使用可能会超出这个代码片段的范围,在这种情况下,您应该按值捕获以避免悬空引用:

MYButton* button;
button->onPress = [=](control*){
            button->foobar(x, y);
    };

来自cpp reference

如果非引用实体被隐式或显式引用捕获,并且在实体的生命周期结束后调用闭包对象的函数调用运算符,则会发生未定义的行为。 C++ 闭包不会延长捕获的引用的生命周期。

还有一条评论。虽然默认捕获在纸上看起来不错(一个字符,没有大惊小怪),但我喜欢明确捕获以减少出现上述错误的风险。它还可以更轻松地识别 lambda 依赖的变量。在这种情况下,代码变为:

MYButton* button;
button->onPress = [button](control*){
            button->foobar(x, y);
    };

这只是风格上的改变——它的含义与之前的示例相同,但在以后修改代码时应该更不容易出错。

【讨论】:

  • 消除 control * 参数可能会使赋值失败,因为 lambda 与回调的类型不匹配 onPress...
  • 我收到了这个Error:(830, 31) '&' must precede a capture when the capture default is '='
  • 您是否将index 留在了捕获列表中?
  • 请注意“如果捕获默认值为 =,则后续简单捕获必须以 & 或 *this(C++17 起)或 this(C++20 起)开头。”跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 2016-02-08
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
相关资源
最近更新 更多