开发者

C++0x lambda vs blocks

开发者 https://www.devze.com 2023-03-28 02:23 出处:网络
I was exploring C++0x to开发者_JAVA百科day, and I encountered the new lambda feature. My question is how are these different (in terms of use) from blocks and why might one prefer one over the other?

I was exploring C++0x to开发者_JAVA百科day, and I encountered the new lambda feature. My question is how are these different (in terms of use) from blocks and why might one prefer one over the other?

Thanks.


there is a a short syntax with C++0x lambdas to take every variable in scope by reference. ([&]) The type of a lambda is also unspecified, allowing potentially more optimal code.

Now, when you look at Apple blocks, it will require __block specifiers added to variables you want to modify (the very fact that this is required suggests the whole system is defective). Variables are taken by reference but then by value when the block exits the scope (and the copied context necessarily lives on the heap, it seems). A weird semantic that will only lead to broken designs, but probably makes people that love GC happy. Without saying this probably has quite the efficiency cost, of course, since this requires special indirections.

It is claimed the C++0x lambdas syntax would break compatibility with C programs, but I don't think that is true. There are probably other problems to integrate it with C, though, mainly the fact that C can't really deal with unspecified types and build type erasure.

Apple blocks is really just an ObjC feature they try to generalize to other languages. For C++, the system designed for that language is just so much better.

EDIT:

To properly give credit, I took this information from http://www.rhinocerus.net/forum/language-c-moderated/558214-blocks-vs-c-lambdas.html a long time ago. That link is dead now; however, the original discussion appears to be archived here, thanks to @stefan for finding it.


I think it basically comes down to a question of your starting point. If you're starting from Objective-C, and writing C++ (Objective-C++) primarily (or exclusively) as an adjunct to Objective-C, then using blocks throughout all the code may make sense, simply to retain as much commonality as possible across the code base. Even if (for example) a project used some pieces written in Objective-C and others in C++, it could make sense to use blocks in both retain as much similarity throughout the code base as possible.

Unless you're using them outside of C++, however, I see little reason to prefer blocks over C++ lambdas. In what I'd guess to be the most common use (a predicate or action in an algorithm) the only noticeable difference between the two would be that one starts with ^ and the other with [].

Older versions of Objective C++

Before the ARC, there were internal differences in the implementation of blocks and lambdas that were likely to affect some more advanced uses. For example, blocks worked vaguely like C strings, so you used Block_copy to copy one, Block_release to free the copy, and so on. On the other hand, in C++ this is all automated so the copy ctor automatically uses Block_copy and the dtor Block_release as needed. At the same time, it did involve a bit more "magic", so (for example) when you copy a block, the copy is always allocated dynamically, regardless of how the source was allocated.

If, for one reason or another, you're stuck with using an older (I'm tempted to say "ancient") compiler or maintaining older code (and don't want to update the codebase as a whole) the memory management difference may be worth taking into account.


Mike Ash provides a detailed comparison. Blocks and lambdas differ in their syntax, their data type, the way they capture variables, the way they behave when copied, and their performance.

How they relate to C/C++/Objective-C:

I will refer to Apple's blocks extension as "Objective-C blocks" even though this is not entirely correct. They are actually an addition to C (and can even be used in C++), with some extra behaviors to make them more useful in Objective-C. However, they are deeply intertwined with Objective-C in their implementation, and "C blocks" is vague, so I think that "Objective-C blocks" is the best way to refer to them here.

C++0x lambdas are part of C++ only and can't be used from C. Presumably they can be used in Objective-C++ if the compiler supports C++0x.

A very high-level summary of the differences:

Objective-C blocks are somewhat simpler to write and to use, especially in the case of using them for asynchronous or background tasks where the block has to be copied and kept alive beyond the lifetime of the scope where it was created. C++0x lambdas ultimately provide more flexibility and potential speed, but at the cost of considerable added complexity.


As of recent clang versions (3.2, 3.3rc and 3.4svn) they are interchangable in Objective-C(++) code. In C++ you have to use lambda, but in Objective-C(++) if you have

  • C++ support in your libobjc.
    Apple's libobjc.B.dylib have it for sure. If you are using GNUstep, you need to either compile libobjc2 (and only libobjc2) with cmake and linking against libsupc++ (or whatever C++ ABI library you use) or link your project against libobjcxx as well
  • Blocks runtime should exist.
    It is part of libSystem.dylib on OS X which libc is linked against so it is not much an issue there. You can use LLVM compiler-rt for this or use libobjc2. I personally recommend you use libobjc2 as it provided a Blocks runtime that is compatible with the rest of GNUstep, which is also called for.
  • Foundation kit.
    This is due to how clang handle the ABI of interchanging C++ lambda and Objective-C blocks. clang do so with NSAutoreleasePool which is part of Foundation.

then you can safely interchange parts.

0

精彩评论

暂无评论...
验证码 换一张
取 消