当前位置: 首页 > 知识库问答 >
问题:

有没有理由不使用全局lambdas?

仇浩旷
2023-03-14

我们有一个函数,该函数使用自身内部的非捕获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
}

将其更改为适当的函数是微不足道的,但这让我想知道是否有理由不将其保留为lambda?是否有任何理由不在任何地方使用lambda而不是“常规”全局函数?

共有3个答案

宦翔飞
2023-03-14

是否有任何理由不在任何地方使用lambda而不是“常规”全局函数?

具有一定复杂性的问题需要至少具有相同复杂性的解决方案。但是,如果同一个问题有一个不太复杂的解决方案,那么就没有理由使用更复杂的解决方案。为什么要引入你不需要的复杂性?

在λ和函数之间,函数只是两者中较不复杂的实体。你不必证明不使用λ。你必须证明使用一个是合理的。lambda表达式引入了一个闭包类型,它是一个未命名的类类型,包含所有常用的特殊成员函数、函数调用操作符,在本例中,它是函数指针的隐式转换操作符,并创建了该类型的对象。从lambda表达式复制初始化全局变量不仅仅是定义函数。它定义了一个具有六个隐式声明函数的类类型,定义了另外两个运算符函数,并创建了一个对象。编译器必须做更多的工作。如果你不需要lambda的任何功能,那么不要使用lambda...

齐永昌
2023-03-14

我可以想到一些您希望避免将全局lambda作为常规函数的替代品的原因:

  • 常规函数可以重载;lambdas不能(然而,有一些技术可以模拟这一点)
  • 尽管它们是类似函数的,即使像这样的非捕获λ也会占用内存(非捕获通常为1字节)。
    • 正如注释中指出的,现代编译器将在as-if规则下优化此存储
    • 类比lambdas有更少的限制,因此应该是您首先要达到的
      • (公共/私有数据、重载、助手方法等)
      • 我们更希望在尽可能小的范围内创建类的实例
      • 类为我们提供了一种简单的方法来创建函数指针,它们也是许多程序员更喜欢的

尤研
2023-03-14

不使用全局lambdas有一个非常重要的原因:因为它不正常。

C的正则函数语法从C时代就已经存在了。几十年来,程序员已经知道所说的语法是什么意思以及它们是如何工作的(尽管不可否认,整个函数到指针的衰减有时甚至会困扰经验丰富的程序员)。如果一个超过“完全新手”技能水平的C程序员看到一个函数定义,他们知道自己得到了什么。

全球lambda是完全不同的野兽。它具有不同于常规函数的行为。Lambda是对象,而函数不是。它们有一个类型,但该类型不同于它们函数的类型。等等。

现在,您提高了与其他程序员沟通的门槛。如果C程序员想要理解这个函数的作用,就需要理解lambdas。是的,现在是2019年,所以一个优秀的C程序员应该知道lambda是什么样子的。但这仍然是一个更高的标准。

即使他们理解了,程序员心中的问题也是...为什么这段代码的作者要这样写?如果您对这个问题没有一个好的答案(例如,因为您明确希望禁止重载和ADL,如Ranges自定义点),那么您应该使用通用机制

在适当的情况下,更喜欢预期的解决方案,而不是新颖的解决方案。用最简单的方法表达你的观点。

 类似资料:
  • 我读到这个关于Java的和之间的区别的问题,后者已经有几年的历史了。让我吃惊的是,只有一个问题提到了使用的任何缺点;也就是说,如果使用大量CPU,加速比就会降低。 假设您不在某种特殊的单线程环境中,是否应该始终选择?有什么理由不这样做吗?请注意,上面问题的一个答案提到,如果元素少于4096个,将直接调用。

  • 关于已回答的问题:Java BufferedReader,将InputStream转换为BufferedReader,Java的BufferedReader和InputStreamReader类之间有什么区别? BufferedReader[BR]和InputStreamReader[ISR]都实现了相同的接口。BR拥有ISR拥有的所有方法以及其他方法,包括非常有用的readLine()方法和不那

  • 问题内容: 我指的是模块中的OrderedDict,这是一个有序的字典。 如果它具有可订购的附加功能,我意识到这通常不是必需的,但是即使如此,是否还有缺点?慢一点吗?是否缺少任何功能?我没有看到任何丢失的方法。 简而言之,为什么我 不 总是使用它而不是普通的词典? 问题答案: 是的子类,并且需要更多内存来跟踪键的添加顺序。这不是小事。该实现在幕后增加了第二个,所有键的双向链接列表(这是记住顺序的部

  • 版本: 返回一个,其ID为“z”,偏移量为0,默认区域规则。 返回一个,包含ID“utc”和。 例如,在处理时。在这里,我能发现的唯一区别是它的打印方式不同。 我们正在来回地进行代码审查讨论,所以我想这种冲突并不罕见。 它是一个常量(此外,它的偏移量值(0)甚至被缓存)。 由于缺少区域信息,它的开销少了一点。 在UTC时,不需要考虑夏时制时间或历史变化,就像在任何其他时区一样。 因此,对于我迄今为

  • 问题内容: 我想全局拦截某些错误情况,以防止控制器自己处理错误。我认为我需要HTTP拦截器,但是我不确定如何从我的控制器中处理错误。 我有一个像这样的控制器: 和这样的HTTP拦截器: 这与浏览器重定向到“ /错误”路径一样有效。但在承诺抓的 也 执行了,我不希望这样。 我知道我可以编写代码,使其忽略404错误,但这是无法维护的。假设我进行修改以同时处理500个错误,那么我将不得不再次进行修改(以

  • 问题内容: 对于2015年9月,以下是在Swift中制作单例的确切方法: 然后在其他地方… 没问题。 然后,您可以在整个项目范围内简单地执行以下操作: 传统习语: Model.shared.blah()…在代码库中到处可见 “我的”成语: model.blah()…在代码库中到处可见 因此,这导致一切看上去都很漂亮: (在你的项目中,那些“单变量”将是一些事情,如,,,或任何情况下可能会在您的项目