C ++ 0x лямбда против блоков - PullRequest
       21

C ++ 0x лямбда против блоков

12 голосов
/ 16 августа 2011

Сегодня я изучал C ++ 0x и столкнулся с новой лямбда-функцией. Мой вопрос: чем они отличаются (с точки зрения использования) от блоков и почему один может предпочесть один другому?

Спасибо.

Ответы [ 4 ]

5 голосов
/ 16 августа 2011

Я думаю, что в основном все сводится к вопросу о вашей отправной точке.Если вы начинаете с Objective-C и пишете C ++ (Objective-C ++) в основном (или исключительно) как дополнение к Objective-C, тогда использование блоков во всем коде может иметь смысл, просто чтобы сохранить как можно больше общности.через базу кода.Даже если (например) проект использовал некоторые фрагменты, написанные на Objective-C, а другие на C ++, может иметь смысл использовать блоки в обоих, сохраняя как можно больше сходства во всей кодовой базе.

Однако, если вы не используете их вне C ++, я не вижу особых причин отдавать предпочтение блокам над C ++ lambdas.В том, что я считаю наиболее распространенным использованием (предикат или действие в алгоритме), единственное заметное различие между ними состоит в том, что один начинается с ^, а другой - с [].

* 1008.* Старые версии Objective C ++

До ARC существовали внутренние различия в реализации блоков и лямбд, которые могли повлиять на некоторые более сложные применения.Например, блоки работали неопределенно, как строки C, поэтому вы использовали Block_copy для копирования одного, Block_release для освобождения копии и так далее.С другой стороны, в C ++ все это автоматизировано, поэтому копирующий ctor автоматически использует Block_copy и dtor Block_release по мере необходимости.В то же время, он включал немного больше «волшебства», поэтому (например), когда вы копируете блок, копия всегда выделяется динамически, независимо от того, как был выделен источник.

Если, дляпо той или иной причине вы застряли с использованием более старого (я испытываю желание сказать «древний») компилятора или поддержки более старого кода (и не хотите обновлять кодовую базу в целом), разница в управлении памятью может стоитьс учетом.

5 голосов
/ 16 августа 2011

существует короткий синтаксис с лямбдами C ++ 0x, чтобы взять каждую переменную в области видимости по ссылке.([&]) Тип лямбды также не указан, что позволяет использовать потенциально более оптимальный код.

Теперь, когда вы смотрите на блоки Apple, потребуется добавить спецификаторы __block к переменным, которые вы хотите изменить (оченьТот факт, что это требуется, говорит о том, что вся система неисправна).Переменные берутся по ссылке, но затем по значению, когда блок выходит из области видимости (и, похоже, скопированный контекст обязательно живет в куче).Странная семантика, которая приведет только к разрушенным конструкциям, но, вероятно, сделает людей, которые любят GC, счастливыми.Разумеется, это, вероятно, имеет довольно низкую эффективность, поскольку требует особых косвенных указаний.

Утверждается, что синтаксис лямбда-выражений C ++ 0x нарушит совместимость с программами на C, но я не думаю, что этоправда.Вероятно, существуют другие проблемы, связанные с его интеграцией с C, но, в основном, тот факт, что C не может справиться с неопределенными типами и стиранием типов сборки.

Блоки Apple - это просто функция ObjC, которую они пытаются обобщить.Другие языки.Для C ++ система, разработанная для этого языка, намного лучше.

РЕДАКТИРОВАТЬ:

Чтобы правильно отдать должное, я взял эту информацию из http://www.rhinocerus.net/forum/language-c-moderated/558214-blocks-vs-c-lambdas.html давным-давно.Эта ссылка сейчас мертва;тем не менее, исходное обсуждение, похоже, заархивировано здесь , спасибо @stefan за то, что нашли его.

1 голос
/ 05 февраля 2018

Майк Эш дает подробное сравнение . Блоки и лямбды различаются по синтаксису, типу данных, способу захвата переменных, поведению при копировании и производительности.

Как они относятся к C / C ++ / Objective-C:

Я буду называть расширение блоков Apple «блоками Objective-C» даже хотя это не совсем правильно. Они на самом деле являются дополнением к C (и может даже использоваться в C ++), с некоторыми дополнительными поведениями, чтобы сделать они более полезны в Objective-C. Тем не менее, они глубоко переплетены с Objective-C в их реализации, а "блоки C" расплывчаты, поэтому Я думаю, что «блоки Objective-C» - лучший способ обратиться к ним здесь.

C ++ 0x lambdas являются частью только C ++ и не могут использоваться из C. Предположительно их можно использовать в Objective-C ++, если компилятор поддерживает C ++ 0x.

Сводка различий очень высокого уровня:

Блоки Objective-C несколько проще в написании и использовании, особенно в случае использования их для асинхронного или фонового задачи, в которых блок должен быть скопирован и сохранен за пределами время существования области, в которой оно было создано. C ++ 0x лямбда в конечном итоге обеспечить большую гибкость и потенциальную скорость, но за счет значительно сложнее.

0 голосов
/ 05 июня 2013

Начиная с последних версий clang (3.2, 3.3rc и 3.4svn) они взаимозаменяемы в коде Objective-C (++). В C ++ вы должны использовать лямбду, но в Objective-C (++), если у вас есть

  • Поддержка C ++ в вашем libobjc.
    У libobjc.B.dylib от Apple это точно есть. Если вы используете GNUstep, вам нужно либо скомпилировать libobjc2 (и только libobjc2) с помощью cmake и связать его с libsupc ++ (или с любой библиотекой C ++ ABI, которую вы используете), либо связать свой проект с libobjcxx, а также
  • Должно существовать время выполнения блоков.
    Это часть libSystem.dylib на OS X, с которой связана libc, так что это не большая проблема. Вы можете использовать LLVM compiler-rt для этого или использовать libobjc2. Я лично рекомендую вам использовать libobjc2, поскольку он предоставляет среду исполнения Blocks, совместимую с остальной частью GNUstep, которая также требуется.
  • Фундаментный комплект.
    Это связано с тем, как clang обрабатывает ABI для обмена лямбда-кодами C ++ и Objective-C. clang делает это с NSAutoreleasePool, который является частью Foundation.

тогда вы можете безопасно менять детали.

...