只在本地使用 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 *** 以在 *** 和本地接口之间拆分流量吗? [关闭]