C++ 绑定与 Lambda?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1930903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:37:18  来源:igfitidea点击:

Bind Vs Lambda?

c++functional-programminglambdac++11bind

提问by AraK

I have a question about which style is preferred: std::bind Vs lambda in C++0x. I know that they serve -somehow- different purposes but lets take an example of intersecting functionality.

我有一个关于首选哪种样式的问题:C++0x 中的 std::bind Vs lambda。我知道它们以某种方式服务于不同的目的,但让我们举一个交叉功能的例子。

Using lambda:

使用lambda

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

Using bind:

使用bind

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

Which one should we prefer? why? assuming more complex situations compared to the mentioned example. i.e. What are the advantages/disadvantages of one over the other?

我们应该更喜欢哪一种?为什么?假设与上述示例相比更复杂的情况。即一个相对于另一个的优点/缺点是什么?

采纳答案by Thomas Petit

As you said, bind and lambdas don't quite exactly aim at the same goal.

正如您所说, bind 和 lambdas 的目标并不完全相同。

For instance, for using and composing STL algorithms, lambdas are clear winners, IMHO.

例如,对于使用和编写 STL 算法,恕我直言,lambda 显然是赢家。

To illustrate, I remember a really funny answer, here on stack overflow, where someone asked for ideas of hex magic numbers, (like 0xDEADBEEF, 0xCAFEBABE, 0xDEADDEAD etc.) and was told that if he were a real C++ programmer he would simply have download a list of English words and use a simple one-liner of C++ :)

为了说明这一点,我记得一个非常有趣的答案,这里是关于堆栈溢出的,有人询问有关十六进制幻数的想法(如 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
    );
}

This snippet, in pure C++98, open the English words file, scan each word and print only those of length 8 with 'a', 'b', 'c', 'd', 'e' or 'f' letters.

这个片段,在纯 C++98 中,打开英文单词文件,扫描每个单词并只打印长度为 8 的带有 'a'、'b'、'c'、'd'、'e' 或 'f' 的单词字母。

Now, turn on C++0X and lambda :

现在,打开 C++0X 和 lambda :

#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);
    }
 );
}

This is still a bit heavy to read (mainly because of the istream_iterator business), but a lot simpler than the bind version :)

这个读起来还是有点重(主要是因为 istream_iterator 业务),但是比 bind 版本简单很多 :)

回答by dv_

C++0x lambdas are monomorphic, while bind can be polymorphic. You cannot have something like

C++0x lambdas 是单态的,而 bind 可以是多态的。你不能有类似的东西

auto f = [](auto a, auto b) { cout << a << ' ' << b; }
f("test", 1.2f);

a and b must have known types. On the other hand, tr1/boost/phoenix/lambda bind allows you to do this:

a 和 b 必须具有已知类型。另一方面,tr1/boost/phoenix/lambda bind 允许你这样做:

struct foo
{
  typedef void result_type;

  template < typename A, typename B >
  void operator()(A a, B b)
  {
    cout << a << ' ' << b;
  }
};

auto f = bind(foo(), _1, _2);
f("test", 1.2f); // will print "test 1.2"

Note that the types A and B are notfixed here. Only when f is actually used these two will be deduced.

请注意,这里的类型 A 和 B不是固定的。只有在实际使用 f 时才会推导出这两个。

回答by pranavsharma

The C++ 0x lamdba syntax is more readable than the bind syntax. Once you get into more than 2-3 level bind, you code becomes pretty much unreadable and difficult to maintain. I would prefer the more intuitive lambda syntax.

C++ 0x lamdba 语法比绑定语法更具可读性。一旦您进入超过 2-3 级绑定,您的代码就会变得非常不可读且难以维护。我更喜欢更直观的 lambda 语法。

回答by R Samuel Klatchko

One of the benefits of lambdas is they are way more useful when you need to add a little big of logic on top of an existing function.

lambda 的好处之一是,当您需要在现有函数之上添加一些大逻辑时,它们会更有用。

With bind, you are forced to create a new function/method/functor even if the logic is only ever needed in this one place. You need to come up with an appropriate name and it can make the code less understandable as it potentially makes you split up related logic.

使用绑定,您被迫创建一个新的函数/方法/函子,即使逻辑只在这个地方需要。您需要想出一个合适的名称,它会使代码更难理解,因为它可能会使您拆分相关的逻辑。

With lambda, you can add the new logic inside the lambda (but are not forced to if it makes sense to create a new callable).

使用 lambda,您可以在 lambda 中添加新逻辑(但如果创建新的可调用对象有意义,则不必强制)。

回答by Kornel Kisielewicz

I think it's more a matter of taste. People that quickly grasp new technologies, or are familiar with functional programming will probably prefer lambda syntax, while more conservative programmers will definitively prefer bind, as it is more in par with the traditional C++ syntax.

我认为这更像是一个品味问题。快速掌握新技术或熟悉函数式编程的人可能更喜欢 lambda 语法,而更保守的程序员肯定会更喜欢 bind,因为它更接近于传统的 C++ 语法。

Such a decision should be made in coordination with the people that will be working with the code, probably through a majority vote.

这样的决定应该与将使用代码的人员协调做出,可能通过多数票。

Which doesn't change the fact however, that lambda syntax is much more powerful and cleaner.

然而,这并没有改变这一事实,即 lambda 语法更加强大和简洁。

回答by Terry Mahaffey

C++0x lambdas essentially replace bind. There is nothing you can bind that you can't recreate a trivial wrapper lambda to achieve the same. std::tr1::bind will go the way of std::bind1st, etc once lambda support is wide spread. Which is good, because for some reason most programmers have a hard time getting their head around bind.

C++0x lambdas 本质上取代了绑定。没有什么可以绑定的,你不能重新创建一个简单的包装器 lambda 来实现相同的目标。一旦 lambda 支持广泛传播,std::tr1::bind 将采用 std::bind1st 等方式。这很好,因为出于某种原因,大多数程序员都很难理解绑定。

回答by plugwash

A key advantage of lambdas is they can reference member functions statically, while bind can only reference them through a pointer. Worse, at least in compilers that follow the "itanium c++ ABI" (e.g. g++ and clang++) a pointer to a member function is twice the size of a normal pointer.

lambda 的一个主要优点是它们可以静态引用成员函数,而 bind 只能通过指针引用它们。更糟糕的是,至少在遵循“itanium c++ ABI”(例如 g++ 和 clang++)的编译器中,指向成员函数的指针的大小是普通指针的两倍。

So with g++ at least, if you do something like std::bind(&Thing::function, this)you get a result that is three pointers in size, two for the pointer to member function and one for the this pointer. On the other hand if you do [this](){function()}you get a result that is only one pointer in size.

所以至少对于 g++,如果你做类似的事情,std::bind(&Thing::function, this)你会得到一个大小为三个指针的结果,两个用于指向成员函数的指针,一个用于 this 指针。另一方面,如果你这样做,[this](){function()}你得到的结果只有一个指针大小。

The g++ implementation of std::function can store up to two pointers without dynamic memory allocation. So binding a member function to this and storing it in a std::function will result in dynamic memory allocation while using a lambda and capturing this will not.

std::function 的 g++ 实现最多可以存储两个指针,而无需动态内存分配。因此,将成员函数绑定到 this 并将其存储在 std::function 中将导致动态内存分配,而使用 lambda 而捕获 this 则不会。