C++ 0x lambdas编码风格

Pav*_*aev 22 c++ lambda coding-style c++11

我想知道人们在编码风格方面是如何使用C++ 0x lambdas的.最有趣的问题是编写捕获列表时有多彻底.一方面,语言允许明确地列出捕获的变量,并且通过"显式优于隐式规则",因此有必要进行详尽的列表以清楚地说明意图.例如:

 int sum;
 std::for_each(xs.begin(), xs.end(), [&sum](int x) { sum += x });
Run Code Online (Sandbox Code Playgroud)

对此的另一个论点是,由于ref-captured本地的生命周期不会因为它们被捕获而改变(因此lambda很容易最终引用其生命周期已经结束的本地),因此使捕获显式有助于减少此类错误并追踪他们.

另一方面,该语言还故意提供了自动捕获所有引用的本地语言的快捷方式,因此很明显它是打算使用的.并且可以声称,对于上面的一个示例,即使使用自动捕获也会非常清楚会发生什么,并且lambda的生命周期不会超出周围的范围,因此没有理由不使用它:

 int sum;
 std::for_each(xs.begin(), xs.end(), [&](int x) { sum += x });
Run Code Online (Sandbox Code Playgroud)

显然,这不一定是全有或全无,但必须有一些理由来决定何时自动捕获,以及何时明确捕获.有什么想法吗?

同样的另一个问题是何时使用逐个拷贝 - [=]以及何时使用按引用捕获 - [&].捕获通过复制显然是安全的,因为没有寿命的问题,所以人们可以说,它应该是默认何时使用,没有必要变异捕捉值(或看到其他地方做了一些修改),并且捕获-在这种情况下,副引用应被视为(可能过早地)优化,仅在明显有所作为的情况下应用.

在另一方面,捕获按引用总是会更快(特别是因为它常常可以优化向下到复制,如果是后者实际上是更快的,对于小的类型和inlineable模板函数如最STL算法),以及是如果lambda永远不会超出其范围(这也适用于所有STL算法),那么安全性是非常安全的,因此在这种情况下默认为引用捕获是一种无关紧要且无害的优化.

你的想法是什么?

jal*_*alf 6

我从未听说过"明确胜过隐性规则"规则,我不同意.当然,有些情况确实如此,但也有很多情况并非如此.这就是为什么0x auto毕竟是用关键字添加类型推断的原因.(以及为什么在可能的情况下已经推断出函数模板参数)有很多情况下隐含是优选的.

我还没有真正使用过C++ lambdas(除了探索VC10测试版),但我大部分时间都会使用后者

std::for_each(xs.begin(), xs.end(), [&](int x) { sum += x });
Run Code Online (Sandbox Code Playgroud)

我的推理?为什么不这样做?很方便.有用.而且它更容易维护.当我修改lambda的主体时,我不必更新捕获列表.我为什么要明确一些编译器比我更了解的东西?编译器可以根据实际使用的内容找出捕获列表.

至于参考和价值的捕获?我会应用与常规功能相同的规则.如果需要引用语义,请通过引用捕获.如果您需要复制语义,请执行此操作.如果其中任何一个会这样做,那么对于小型类型更喜欢值,如果复制是昂贵的则参考.

它与设计常规功能时的选择似乎没有什么不同.

我应该阅读lambdas的规范,但这不是显式捕获列表的主要原因,以便您可以通过值捕获一些变量而通过引用捕获其他变量?

  • 关于"编译器比我更了解" - 编译器不知道lambda的生命周期.如果你在外部作用域中将`[&]`lambda分配给`std :: function`,它会很乐意让你这样做然后离开lambda作用域 - 但是,当然,lambda中的所有引用都是无效的当你真正称它为... (2认同)

Ste*_*sop 2

我最初的直觉是,按值捕获提供的功能或多或少与 Java 的匿名内部类相同,后者是已知的数量。但是,当您希望封闭范围可变时,您可以通过引用捕获,而不是使用 array-of-size-1 技巧。然后,您有责任将 lambda 的持续时间限制在引用对象的范围内。

在实践中,我同意你的观点,在处理算法时,通过引用捕获应该是默认的,我预计这将是大多数用途。Java 中匿名内部类的常见用途是侦听器。首先,在 C++ 中可以看到的侦听器样式接口较少,因此需求较少,但仍然存在。在这种情况下,最好严格坚持按价值捕获,以避免出现错误的机会。或许,shared_ptr 的按值捕获会是一个大习惯吗?

然而,我还没有使用过 lambda,所以我很可能错过了一些重要的事情。