【问题标题】:C++0x lambda vs blocksC++0x lambda vs 块
【发布时间】:2011-08-15 22:13:37
【问题描述】:

我今天在探索 C++0x,遇到了新的 lambda 特性。我的问题是这些与blocks 有何不同(在使用方面),为什么有人会更喜欢其中一个?

谢谢。

【问题讨论】:

  • 我更喜欢 lambda,因为它们是标准的,因此可以在符合最新标准的编译器之间移植,并且可以轻松地与标准库一起使用。
  • @Matteo:块也是如此——在 Objective C 中
  • @Vlad:在 Objective C 中你没有 lambda,所以“在两个选项之间进行选择”是没有意义的——因为只有块可用。您“可能更喜欢其中一个”的唯一情况是您可以选择,即在 C++ 中使用 Clang(我所知道的唯一支持两者的编译器),在这种情况下我会使用 lambdas(除非你有一些复杂的C++/Objective C 混合项目,但我不是这种情况的专家)。
  • 块不只是 Objective-c 我已经在 Ubuntu 上用 Clang 和 llvm 的用于 Block_copy 和 Block_release 的 compiler-rt 库使用它们
  • @newacct:Apple 的 Objective C 方言不是 de facto 标准吗?

标签: c++ lambda c++11 objective-c-blocks


【解决方案1】:

C++0x lambda 有一个简短的语法来获取每个变量 参考范围。 ([&]) lambda 的类型也未指定, 允许更优化的代码。

现在,当您查看 Apple 块时,它需要 __block 说明符 添加到要修改的变量中(事实上,这是 required 表明整个系统有缺陷)。变量被取走 通过引用,然后在块退出范围时按值(以及 似乎复制的上下文必然存在于堆上)。一个奇怪的 语义只会导致设计损坏,但可能会使 爱GC的人快乐。不用说这可能有相当的 当然,效率成本,因为这需要特殊的间接性。

据称 C++0x lambdas 语法会破坏与 C 程序,但我认为这不是真的。大概还有其他 但是,将它与 C 集成的问题主要是 C 不能 真正处理未指定的类型并构建类型擦除。

Apple 块实际上只是他们试图推广到的 ObjC 功能 其他语言。对于 C++,为该语言设计的系统是 好多了。

编辑:

为了恰当地给予信任,我很久以前从http://www.rhinocerus.net/forum/language-c-moderated/558214-blocks-vs-c-lambdas.html 获取了这些信息。该链接现在已失效;但是,原始讨论似乎已存档 here,感谢 @stefan 找到它。

【讨论】:

  • 另外,lambda 是 c++ 的一部分,块不是。所以 lambda 是可移植的。不阻止。
  • @djhaskin987 此链接是否指向您资源的正确存档版本:comp.lang.cpp.moderated.narkive.com/QqL0BZS2/…?
  • 这句话有很多问题。变量不是按引用获取,而是始终按值获取(__block 变量始终按引用获取); “当块退出范围时”没有什么特别的事情发生。
【解决方案2】:

我认为这基本上归结为您的起点问题。如果您是从 Objective-C 开始,并且主要(或专门)编写 C++(Objective-C++)作为 Objective-C 的附属品,那么在所有代码中使用块可能是有意义的,只是为了尽可能多地保留共性跨代码库。即使(例如)一个项目使用了一些用 Objective-C 编写的部分和其他用 C++ 编写的部分,可能在两者中使用块在整个代码库中保持尽可能多的相似性。 p>

但是,除非您在 C++ 之外使用它们,否则我认为没有理由更喜欢块而不是 C++ lambda。我猜这是最常见的用途(算法中的谓词或动作),两者之间唯一明显的区别是一个以^开头,另一个以[]开头。

Objective C++ 的旧版本

在 ARC 之前,块和 lambda 的实现存在内部差异,这可能会影响一些更高级的用途。例如,块的工作方式有点像 C 字符串,所以您使用 Block_copy 复制一个,使用 Block_release 释放副本,等等。另一方面,在 C++ 中,这一切都是自动化的,因此复制 ctor 会根据需要自动使用 Block_copy 和 dtor Block_release。同时,它确实涉及到更多的“魔法”,所以(例如)当你复制一个块时,副本总是动态分配的,不管源是如何分配的。

如果出于某种原因,您坚持使用较旧的(我很想说“古老”)编译器或维护较旧的代码(并且不想整体更新代码库)内存管理差异可能值得考虑。

【讨论】:

  • 这个答案可能应该更新,因为我们知道在 Objective-C++ 中,块和 lambda 是等价的(它们可以相互分配、可复制,并且它们现在都是由系统,而不是用户(ARC 负责)。
【解决方案3】:

Mike Ash 提供了一个detailed comparison。块和 lambda 在语法、数据类型、捕获变量的方式、复制时的行为方式以及性能方面有所不同。

它们与 C/C++/Objective-C 的关系:

我甚至将 Apple 的块扩展称为“Objective-C 块” 虽然这并不完全正确。它们实际上是对 C(甚至可以在 C++ 中使用),需要做一些额外的行为 它们在 Objective-C 中更有用。然而,它们却是紧密相连的 在他们的实现中使用 Objective-C,并且“C 块”是模糊的,所以 我认为“Objective-C 块”是引用它们的最佳方式 在这里。

C++0x lambda 只是 C++ 的一部分,不能在 C 中使用。 如果编译器支持,大概它们可以在 Objective-C++ 中使用 C++0x。

对差异的高度概括:

Objective-C 块更易于编写和使用, 特别是在将它们用于异步或后台的情况下 块必须被复制并保持活动状态的任务 创建它的作用域的生命周期。 C++0x lambdas 最终 提供更大的灵活性和潜在的速度,但代价是 相当多的复杂性。

【讨论】:

    【解决方案4】:

    从最近的 clang 版本(3.2、3.3rc 和 3.4svn)开始,它们可以在 Objective-C(++) 代码中互换。在 C++ 中你必须使用 lambda,但在 Objective-C(++) 中如果你有

    • libobjc 中的 C++ 支持。
      苹果的 libobjc.B.dylib 肯定有它。如果您使用的是 GNUstep,您需要使用 cmake 编译 libobjc2(并且只有 libobjc2)并链接到 libsupc++(或您使用的任何 C++ ABI 库),或者也将您的项目链接到 libobjcxx
    • 应该存在块运行时。
      它是 OS X 上 libSystem.dylib 的一部分,libc 与之链接,因此在那里它不是什么大问题。您可以为此使用 LLVM compiler-rt 或使用 libobjc2。我个人建议您使用 libobjc2,因为它提供了与 GNUstep 的其余部分兼容的 Blocks 运行时,这也是需要的。
    • 基础套件。
      这是由于 clang 如何处理交换 C++ lambda 和 Objective-C 块的 ABI。 clang 使用 Foundation 中的 NSAutoreleasePool 来实现。

    那么您就可以安全地更换零件了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-08
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      相关资源
      最近更新 更多