我们有一个函数使用了自身内部的非捕获lambda,例如:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
现在其他地方都需要由lambda实现的功能,因此我将把lambda从foo()
提升到全局/命名空间范围。我可以将其保留为lambda,使其成为复制粘贴选项,也可以将其更改为适当的功能:
auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2
void foo() {
// code using bar(x,y) a bunch of times
}
将其更改为适当的功能是微不足道的,但是这使我想知道是否有某些理由 not 将其保留为lambda?是否有理由不只是在各处使用lambda而不是“常规”全局函数?
答案 0 :(得分:45)
我可以想到一些您希望避免将全局lambda替换为常规函数的现成原因的原因:
答案 1 :(得分:45)
一个不使用全局Lambda的重要原因是:这是不正常的。
C ++的常规函数语法自C语言诞生以来就已经存在。数十年来,程序员都知道语法的含义以及它们的工作方式(尽管公认,整个函数到指针的衰减有时甚至会咬住经验丰富的程序员)。如果具有“完全新手”以外的任何技能水平的C ++程序员都可以看到函数定义,那么他们知道自己正在获得什么。
全局lambda完全是另一种野兽。它具有与常规功能不同的行为。 Lambda是对象,而功能不是。它们具有一个类型,但是该类型不同于其功能的类型。依此类推。
因此,现在,您已经提高了与其他程序员交流的门槛。如果C ++程序员想要了解该函数的功能,则需要了解它们。是的,这是2019年,所以一个体面的C ++程序员应该对lambda的外观有所了解。但这仍然是一个更高的标准。
即使他们理解它,该程序员的脑海中的问题仍将是...为什么此代码的编写者以这种方式编写它?而且,如果您对这个问题没有一个好的答案(例如,因为您明确地想要禁止重载,如Ranges定制点中所示),则应使用通用机制。
在适当的情况下,将预期的解决方案优先于新颖的解决方案。使用最简单的方法来表达观点。
答案 2 :(得分:7)
询问后,我想到了一个不这样做的原因:由于这些是变量,因此它们容易发生静态初始化顺序失败(https://isocpp.org/wiki/faq/ctors#static-init-order),这可能会导致错误。线。
答案 3 :(得分:6)
是否有理由不只是在各处使用lambda而不是“常规”全局函数?
某种程度的复杂性问题要求至少具有相同复杂性的解决方案。但是,如果针对同一问题的解决方案不太复杂,那么实际上没有理由使用更复杂的解决方案。为什么要引入不需要的复杂性?
在lambda和函数之间,函数只是两者中不太复杂的一种。您不必证明不使用lambda。您必须证明使用一个。 lambda表达式引入了一个闭包类型,它是具有所有常用特殊成员函数的未命名类类型,函数调用运算符,在这种情况下,还包括隐式转换运算符到函数指针,并创建该类型的对象。从lambda表达式中复制初始化全局变量不仅仅定义一个函数,还执行了很多的工作。它定义了具有六个隐式声明的函数的类类型,定义了另外两个运算符,并创建了一个对象。编译器必须做更多的事情。如果您不需要lambda的任何功能,请不要使用lambda…
答案 4 :(得分:5)
Lambda是anonymous functions。
如果您使用命名的lambda,则意味着您基本上是在使用命名的匿名函数。为了避免这种矛盾,您不妨使用一个函数。
答案 5 :(得分:4)
是否出于某些原因不将其保留为lambda?是否有理由不只是在各处使用lambda而不是“常规”全局函数?
我们过去使用函数而不是全局函子,因此破坏了一致性和最小惊讶的原理。
主要区别在于: