Связать по сравнению с лямбдой?

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

Используя lambda:

uniform_int<> distribution(1, 6);
mt19937 engine;
// lambda style
auto dice = [&]() { return distribution(engine); };

Используя bind:

uniform_int<> distribution(1, 6);
mt19937 engine;
// bind style
auto dice = bind(distribution, engine);

Какой мы должны предпочесть? почему? принятие более сложных ситуаций по сравнению с упомянутым примером. т.е. Каковы преимущества/недостатки одного по другому?

52
задан AraK 18 December 2009 в 11:58
поделиться

5 ответов

Как вы сказали, связывание и лямбды не совсем точно преследуют одну и ту же цель.

Например, для использования и составления алгоритмов STL, лямбды - явные победители, ИМХО.

Для иллюстрации, я помните действительно забавный ответ, здесь, о переполнении стека, где кто-то спросил идеи шестнадцатеричных магических чисел (например, 0xDEADBEEF, 0xCAFEBABE, 0xDEADDEAD и т. д.) и ему сказали, что если бы он был настоящим программистом на C ++, он бы просто загрузил список Английские слова и используйте простой однострочник C ++ :)

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

int main()
{
    using namespace boost::lambda;
    std::ifstream ifs("wordsEn.txt");
    std::remove_copy_if(
        std::istream_iterator<std::string>(ifs),
        std::istream_iterator<std::string>(),
        std::ostream_iterator<std::string>(std::cout, "\n"),
        bind(&std::string::size, _1) != 8u
            ||
        bind(
            static_cast<std::string::size_type (std::string::*)(const char*, std::string::size_type) const>(
                &std::string::find_first_not_of
            ),
            _1,
            "abcdef",
            0u
        ) != std::string::npos
    );
}

Этот фрагмент, на чистом C ++ 98, откройте файл английских слов, просканируйте каждое слово и напечатайте только те, длина которых 8 с 'a', 'буквы b ',' c ',' d ',' e 'или' f.

Теперь включите C ++ 0X и лямбда:

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>

int main()
{
 std::ifstream ifs("wordsEn.txt");
 std::copy_if(
    std::istream_iterator<std::string>(ifs),
    std::istream_iterator<std::string>(),
    std::ostream_iterator<std::string>(std::cout, "\n"),
    [](const std::string& s)
    {
       return (s.size() == 8 && 
               s.find_first_not_of("abcdef") == std::string::npos);
    }
 );
}

Это все еще немного сложно читать (в основном из-за istream_iterator business), но намного проще, чем версия с привязкой :)

26
ответ дан 7 November 2019 в 09:20
поделиться

Синтаксис Lamdba C ++ 0x более читабелен, чем синтаксис связывания. Как только вы попадаете на более чем 2-3 уровня привязки, ваш код становится практически нечитаемым и сложным в сопровождении. Я бы предпочел более интуитивный синтаксис лямбда.

18
ответ дан 7 November 2019 в 09:20
поделиться

Я думаю, это скорее дело вкуса. Люди, которые быстро разбираются в новых технологиях или знакомы с функциональным программированием, вероятно, предпочтут лямбда-синтаксис, в то время как более консервативные программисты определенно предпочтут привязку, поскольку она больше соответствует традиционному синтаксису C ++.

Такое решение должно быть принято в координация с людьми, которые будут работать с кодом, вероятно, посредством большинства голосов.

Однако это не меняет того факта, что лямбда-синтаксис намного мощнее и чище.

3
ответ дан 7 November 2019 в 09:20
поделиться

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

При связывании вы вынуждены создавать новую функцию / метод / функтор, даже если логика когда-либо нужна только в этом месте. Вам нужно придумать подходящее имя, и это может сделать код менее понятным, так как потенциально заставит вас разделить связанную логику.

С помощью лямбда вы можете добавить новую логику внутри лямбда (но не обязаны делать это, если она имеет смысл создать новый вызываемый объект).

8
ответ дан 7 November 2019 в 09:20
поделиться

C++0x lambdas по сути заменяют связывание. Нет ничего, что можно было бы связать, что нельзя было бы воссоздать тривиальную оберточную лямбду для достижения того же самого. std::tr1::bind пойдет по пути std::bind1st, и т.д., как только поддержка лямбды получит широкое распространение. Что хорошо, потому что по каким-то причинам большинству программистов трудно ориентироваться в связке

.
1
ответ дан 7 November 2019 в 09:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: