什么时候更喜欢lambda中的显式捕获而不是隐式捕获?

时间:2015-12-22 16:49:12

标签: c++ c++11 lambda

有时我会在本地函数中执行std::find_if(例如),其中包含5个局部变量,包括参数。但是,传入STL算法的lambda只需要访问其中的1个。我可以通过以下两种方式之一来捕获它:

void foo(int one, int two, int three)
{
    std::vector<int> m_numbers;
    int four, five;

    std::find_if(m_numbers.begin(), m_numbers.end(), [=](int number) {
        return number == four;
    });
}

或者我能做到:

void foo(int one, int two, int three)
{
    std::vector<int> m_numbers;
    int four, five;

    std::find_if(m_numbers.begin(), m_numbers.end(), [four](int number) {
        return number == four;
    });
}

(注意我没有编译此代码,对任何语法错误或其他错误道歉)

我知道隐式捕获基于 odr-used 规则,因此在功能和实现方面,我认为两者都是相同的。什么时候使用显式捕获而不是隐式捕获?我唯一的想法与封装原则有些相关:只能访问所需的东西,编译器可以帮助您确定何时访问变量。它还保持方法的本地状态(它的不变量,在执行期间函数的生命周期)更安全。但这些是真正的实际问题吗?

是否存在使用显式捕获而非隐式捕获的功能性原因?遵循什么是好的经验法则或最佳实践?

2 个答案:

答案 0 :(得分:3)

在运行时使用[=][&]是最简单和最有效的,而无需命名任何名称。

在这些情况下,如this answer所述,只有在 odr-used 时才会捕获变量。换句话说,编译器只捕获所需的内容。

如果指定捕获列表,则可能会出现两个差异:

  • 你忘了捕捉lambda使用的东西
  • 你抓住了lambda不需要的东西。

在第二种情况下,如果按值捕获,则表示该对象被不必要地复制。

所以,我的建议是使用[][&][=],除非你能想到特定情况的其他理由。其中一种情况可能是你想通过引用捕获一些变量,有些则按值捕获。

答案 1 :(得分:3)

  • 显式捕获总是更可取,因为它不易出错
  • 最好使用&amp;如果是重物(不是简单的int,double等)
  • 当您计划在变量捕获范围之外使用lambda时使用=。随着&amp;获取悬挂引用本地销毁变量
  • 是有风险的