只在本地使用 lambda 可以吗? [关闭]

Posted

技术标签:

【中文标题】只在本地使用 lambda 可以吗? [关闭]【英文标题】:Is it ok to use lambda just locally? [closed] 【发布时间】:2018-11-15 22:41:19 【问题描述】:

是否可以定义一个仅在本地使用的 lambda 函数,即在当前块(函数/方法)中?考虑一下某些代码将被执行多次(因此将其放入函数中是合乎逻辑的)但它永远不会在块外使用的情况。

void foo() 
    auto bar = []() 
        // some code applicable only inside foo()
    ;

    bar();
    bar();
    bar();

与将bar() 声明为普通函数相比,这种方法有哪些优点和缺点?

【问题讨论】:

我会将bar 提取到一个单独的函数中,以便对其进行正确测试。 @VTT:我从不以预期测试框架的方式编写代码。也许这就是教条,并解释了为什么我的测试人员不太喜欢我。 我喜欢这样做是因为它避免了 (a) 函数内部的代码重复,或者 (b) 类接口具有过多的私有成员函数,而这些私有成员函数只能从一个函数中调用。跨度> @Bathsheba - 我也不编写预期测试的代码;在实现它的代码之前编写测试更有效! 被测函数是 foo()。 bar 是如何编写 foo 以通过测试的实现细节。 【参考方案1】:

如果可以选择这样做,那么可以,请将 lambda bar 本地化到特定函数。

在 C++ 中,我们总是尽量让对象保持本地化。 (使代码更易于遵循,简化文档,便于重构,&c. &c..)

【讨论】:

@Quentin:现在更好,还是我应该伸手去拿咖啡壶? @Bathsheba :关于这种方法的缺点。你有什么意见吗?我只是好奇。 现在这就是我所说的“基于意见的答案”......“尽可能保持对象本地化”并不意味着实现类和函数尽可能接近。其他陈述也颇有争议,例如,我不会将充满 lambda 调用的堆栈称为“更容易理解”。 dimm 的回答中有一些有趣的想法......我认为这是避免代码重复的好选择,如果 bar 无论如何都与 foo 紧密耦合(甚至可能是一些局部变量在关闭中)。如果 bar 可以 独立使用(即使不是),我更喜欢单独的函数(-> 可重用性)。 当我本地化一个函数时,我的意思是“我保留更改该函数的权利,而无需重新编译和重新测试整个该死的项目”。为此,我不同意如果“它可以被重复使用”的理想主义。【参考方案2】:

我同意这是一种很好的做法。高级逻辑几乎总是比低级逻辑更容易阅读。我经常这样写函数:

void foo()

  // introduce actors here
  auto something = make_something();

  // introduce detailed definitions
  auto bing = [&]()->bool  ... ;  // define what binging means

  auto bong = [&]()  ... ;  // define what bonging means

  // perform logic
  while (bing())
    bong();

请记住,从 c++17 开始,lambda 默认为 constexpr。 gcc 等人。经常将它们完全优化掉。这些都不是性能考虑因素。

【讨论】:

【参考方案3】:

你可以做到。主要问题是它会更具可读性吗?把它放在外面可以减少一层缩进。

你应该问的问题:

    有短线功能吗? 是纯函数还是修改了什么? 它是否与 foo 密切相关,或者可以在其他地方重用? 您想要其他级别的缩进吗?

【讨论】:

【参考方案4】:

从正确性/标准的角度来看,这当然可以。除此之外,这个问题很大程度上是基于意见的。

Lambda 是 C++ 中的众多工具之一。他们在“复制粘贴以供重用”(代码异味)和“将其提取到函数中”之间添加了另一层结构。我个人很喜欢函数局部 lambdas 正是出于列出的目的:你正在重用一小段代码,它只在这个函数范围内有意义。

有理由认为它仍然应该是它自己的函数(因为你所有的函数都是 5 行或更短,对吧?好吧,我怀疑......)。特别是,如果您想重用该 lambda 代码,它应该绝对成为它自己的函数。但在此之前,值得考虑将这段代码就在在它使用的位置旁边,而不是一个屏幕或更多滚动的好处。此外,这两种方法都为操作命名,但 lambda 需要较少的编写开销(例如私有成员函数膨胀)。在同一页面上,将私有成员函数添加到标头会触发重新编译,而在 .cpp 中添加 lambda 则不会。

最后,考虑什么会使代码最易读。如果使用 lambda 或将其提取到函数中的代码清晰度差异很小(并非不可能),那么 编写 代码的便利性就开始变得重要,因此上述考虑因素发挥了作用。

至于测试,这取决于您想要测试的细粒度。像 return a && b && (a == b); 这样的 lambda 表达式真的需要测试吗?如果它只是内联使用(即不提取为 lambda 或函数),你会测试它吗?在某些时候它会成为浪费时间,但在 SO 答案中确定这一点是不可能的。

【讨论】:

【参考方案5】:

这并没有错,实际上这是 lambda 的一大优势:您可以在需要它们的地方本地定义它们,而不必编写仿函数类型。如果你想在尽可能最窄的范围内定义/声明你的东西,那么 lambdas 是你的朋友。

你甚至可以更进一步,做这样的事情:

 auto bar = []() return true;();

定义 lambda 并调用它,全部在一行中。

【讨论】:

这对于构造函数的初始化列表很有趣:C(/*...*/) : m([]( /*... */) /*... */ (/*...*/)) ,特别是如果该成员不是默认可构造的...... @Aconcagua 我无法自拔,但对我来说最有趣的部分是[]()(); 是有效代码,并且可能是编写 noop 的最奇特方式 :) 希望您不想以这种方式产生真正的纳秒延迟... @user463035818:我觉得[]()更美观。

以上是关于只在本地使用 lambda 可以吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

可以配置 OS X *** 以在 *** 和本地接口之间拆分流量吗? [关闭]

Chrome 关闭标签 Vuejs 后删除本地存储

ios - 应用程序关闭时本地通知不更新徽章编号

pyspark 需要本地安装 Spark 吗?

Android ,我们可以使用 Parse LocalDataStore 进行本地存储吗?

本地机密存储是敏感数据的最佳做法吗? [关闭]