我们有一个函数,它使用了自身内部的非捕获 lambda,例如:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Run Code Online (Sandbox Code Playgroud)
现在 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
}
Run Code Online (Sandbox Code Playgroud)
将其更改为适当的函数是微不足道的,但这让我想知道是否有理由不将其保留为 lambda?有什么理由不只是到处使用 lambda 而不是“常规”全局函数?
Nic*_*las 66
不使用全局 lambda 的一个非常重要的原因是:因为它不正常。
C++ 的常规函数语法从 C 时代就已经存在了。几十年来,程序员已经知道所说的语法意味着什么以及它们是如何工作的(尽管不可否认,整个函数到指针衰减的事情有时甚至会让经验丰富的程序员感到厌烦)。如果一个 C++ 程序员在“完全新手”之外的任何技能水平上看到一个函数定义,他们就会知道他们得到了什么。
全局 lambda 是完全不同的野兽。它具有与常规函数不同的行为。Lambda 是对象,而函数不是。它们有一个类型,但该类型与其函数的类型不同。等等。
所以现在,您提高了与其他程序员交流的标准。如果 C++ 程序员要理解这个函数在做什么,他们就需要理解 lambdas。是的,这是 2019 年,所以一个体面的 C++ 程序员应该知道 lambda 的样子。但它仍然是一个更高的标准。
即使他们理解它,那个程序员心中的问题也会是……为什么这段代码的作者要这样写?如果你对这个问题没有很好的答案(例如,因为你明确想要禁止重载和 ADL,就像在 Ranges 自定义点中一样),那么您应该使用通用机制。
在适当的情况下,更喜欢预期的解决方案而不是新颖的解决方案。使用最简单的方法来表达你的观点。
And*_*dyG 53
我可以想到一些您希望避免将全局 lambdas 作为常规函数的替代品的原因:
Mic*_*zel 10
有什么理由不只是到处使用 lambda 而不是“常规”全局函数?
具有一定复杂性的问题需要至少具有相同复杂性的解决方案。但是如果对于同一问题有一个不太复杂的解决方案,那么使用更复杂的解决方案确实没有道理。为什么要引入不需要的复杂性?
在 lambda 和函数之间,函数只是两者中较简单的实体。您不必证明不使用 lambda 是合理的。你必须证明使用一个是合理的。一个 lambda 表达式引入了一个闭包类型,它是一个未命名的类类型,具有所有常用的特殊成员函数、一个函数调用运算符,在这种情况下,一个隐式转换运算符到函数指针,并创建该类型的对象。从 lambda 表达式复制初始化全局变量所做的不仅仅是定义一个函数。它定义了一个具有六个隐式声明函数的类类型,定义了另外两个运算符函数,并创建了一个对象。编译器必须做更多的事情。如果您不需要 lambda 的任何功能,则不要使用 lambda……
询问后,我想到了一个不这样做的原因:由于这些是变量,它们很容易出现静态初始化顺序失败(https://isocpp.org/wiki/faq/ctors#static-init-order),这可能导致错误。
如果有什么理由不把它作为一个lambda?有什么理由不只是到处使用 lambda 而不是“常规”全局函数?
我们曾经使用函数而不是全局函子,因此它打破了一致性和最小惊讶原则。
主要区别是:
归档时间: |
|
查看次数: |
8008 次 |
最近记录: |