这4个lambda表达式之间有什么区别?

时间:2018-10-25 09:45:58

标签: c++ lambda anonymous-function

我知道对于 non-noob sendmail_path = /usr/local/bin/catchmail -f someone@domain.com开发人员来说这似乎很愚蠢,但是这4个lambda表达式之间有什么区别? Code

C++

似乎也一样吗?是使用两种不同的“符号”,还是将值用作闭包?

4 个答案:

答案 0 :(得分:7)

在这种情况下,它们都产生相同的结果。但是,它们之间存在逻辑差异。

  • [](double value) { return MyFunction(value, 1.0, 2.0); }

    这是一个lambda,它接受类型为value的单个参数,并将其传递给MyFunction。从return语句推断出它的返回类型为MyFunction的返回类型,即double.

  • [](double value) -> double { return MyFunction(value, 1.0, 2.0); }

    这与以前的lambda相同,但是这次将其返回类型显式指定为double。在这种情况下是相同的,但是如果MyFunction的返回类型是其他类型,则它将与第一个不同。在这种情况下,第一个将返回MyFunction返回的内容,而第一个仍将返回double

  • [value](double value) { return MyFunction(value, 1.0, 2.0); }

    这取决于所使用的标准版本。在C ++ 11和14中,该变量捕获main的局部变量value。但是,该捕获被lambda的参数value隐藏,因此实际上是无用的。如果lambda被声明为例如[value](double v) { return MyFunction(value, 1.0, 2.0); }。这将传递给捕获的value,而不是其参数。

    在C ++ 17及更高版本中,它已更改,并且实际上是格式错误的(编译错误)。不再允许将lambda参数命名为与您捕获的参数相同的名称。

    由于更改是缺陷报告(CWG 2211),因此它是追溯应用的,因此即使在早期的C ++版本中,编译器也拒绝此类代码是合法的。

  • [value](double value) -> double { return MyFunction(value, 1.0, 2.0); }

    与lambda数字3相同,具有明确的返回类型说明(3和4之间的差与1和2之间的差完全相同)。

答案 1 :(得分:5)

第二个lambda与第一个lambda不同,因为您已明确指定返回类型。由于推导的第一个lambda的返回类型相同,因此没有区别。

第三和第四个lambda格式错误,因为它们声明的参数名称与捕获名称相同。参见标准规则:

  

[expr.prim.lambda.capture]

     

如果简单捕获中的标识符显示为lambda声明符的parameter-claration-clause子句的参数的声明符-id,则程序格式错误。   [示例:

void f() {
  int x = 0;
  auto g = [x](int x) { return 0; }    // error: parameter and simple-capture have the same name
}
     

-示例   ]

此措辞在C ++ 17中被采用。

答案 2 :(得分:3)

第一个lambda是常规的。

第二个lambda表示其返回类型为double

最后两个lambda没声音。 value都是通过值及其参数捕获的,不应尝试使用它(警告表示捕获无法正常进行)。要么是参数,要么是捕获的变量(按值或ref)。

我想,它们应该是这样的:

[foo](double value) { return MyFunction(value, 1.0, foo); }, value);

答案 3 :(得分:1)

第一个和第二个lambda之间以及第三个和第四个lambda之间的区别是,您明确指定或不指定返回类型。在这里它产生相同的功能。

前两个Lambda和第三个Lambda和第四个Lambda之间的差异正在捕获。但是您的示例不适合说明捕获的效果。查看以下代码(live demo)。

int main()
{    
    double v = 100.0;

    auto lam1= [](double val) { return MyFunction(val, 1.0, 2.0); }; //A
    auto lam2= [v](double val) { return MyFunction(v, 1.0, 2.0); }; //B
    auto lam3= [&v](double val) { return MyFunction(v, 1.0, 2.0); }; //C

    FunctionWrapper( lam1, v++ ); //1
    FunctionWrapper( lam2, v++ ); //2
    FunctionWrapper( lam3, v++ ); //3
    std::cout << "v: " << v << '\n';
}

虽然lam1没有捕获任何内容,但是lam2通过值捕获了v,而lam3通过引用捕获了v。三个FunctionWrapper调用的输出分别是103、103、106。这是因为尽管v//1行中已更改,但它的旧值仍在//2行中使用。也就是说,按值捕获意味着v在行lam2中初始化//B时保存的值lam2存储在//3中。另一方面,在v行中,使用lam3的当前值。这是因为v拥有对{{1}}的引用。