这 4 个 lambda 表达式之间有什么区别?
What are the differences between these 4 lambda expressions?
我知道这对于非菜鸟C++
开发人员来说似乎非常愚蠢,但是这 4 个 lambda 表达式之间有什么区别? 法典:
#include <iostream>
#include <math.h>
#include <functional>
inline double MyFunction(double a, double b, double c) {
return (a + b + c);
}
inline void FunctionWrapper(std::function<double(double)> tempFunct, double value) {
std::function<double(double)> funct;
funct = tempFunct;
std::cout << "result: " << funct(value) << std::endl;
}
int main()
{
double value = 100.0;
FunctionWrapper([](double value) { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([](double value) -> double { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([value](double value) { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([value](double value) -> double { return MyFunction(value, 1.0, 2.0); }, value);
}
似乎也是这样吗?要么使用两种不同的"符号"并使用值作为闭包?
在这种情况下,它们都产生相同的结果。但是,它们之间存在逻辑差异。
-
[](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); }
这与以前相同,但这次它的返回类型被明确指定为
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 之间的差异完全相同(。
第二个 lambda 与第一个 lambda 的不同之处在于您显式指定了返回类型。由于第一个 lambda 的推导返回类型相同,因此没有区别。
第三个和第四个 lambda 的格式不正确,因为它们声明了一个与捕获同名的参数。请参阅标准规则:
[expr.prim.lambda.capture]
如果简单捕获中的标识符显示为 lambda 声明符的参数的参数的声明符 id,则程序格式不正确。 [ 示例:
void f() { int x = 0; auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name }
— 结束示例 ]
这一措辞于C++17年通过。
第一个 lambda 是通常的。
第二个 lambda 表示其返回类型为double
。
最后两个 lambda 不合理。value
都是由值及其参数捕获的,不应尝试(有一条警告指示捕获不起作用(。它要么是参数,要么是捕获的变量(按值或引用(。
我想,它们应该是这样的:
[foo](double value) { return MyFunction(value, 1.0, foo); }, value);
第一个和第二个 lambda 之间的区别以及第三个和第四个 lambda 之间的区别在于,您要么显式指定返回类型,要么不显式指定返回类型。在这里,它会产生相同的功能。
您的前两个 lambda 与 lambda 3 和 4 之间的区别在于捕获。但是您的示例不适合说明捕获的效果。查看以下代码(现场演示(。
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
行中使用。也就是说,按值捕获意味着在行中初始化lam2
时v
持有的值//B
存储在lam2
中。另一方面,在行//3
中使用v
的当前值。这是因为lam3
持有对v
的引用。
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- typedef 枚举和枚举类有什么区别?
- &C::c 和 &(C::c) 有什么区别?
- ascii 和 unicode 在处理级别有什么区别吗?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- "ABC" 和 "ABC" ) 在C++中有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 这两种C++语法之间有什么区别?
- lua 5.0.2 模块和 5.3.5 有什么区别?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- std::enable_if 和 std::enable_if_t 有什么区别?