c++ - 为什么在 C++14 中使用 std::bind 而不是 lambda?

标签 c++ lambda bind c++14

在 C++11 之前,我经常使用 boost::bindboost::lambdabind 部分进入标准库(std::bind),另一部分成为核心语言的一部分(C++ lambdas)并大量使用 lambdas更轻松。现在,我几乎不使用 std::bind,因为我几乎可以用 C++ lambda 做任何事情。我能想到 std::bind 的一个有效用例:

struct foo
{
  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"

对应的 C++14 是

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

更短更简洁。 (在 C++11 中,由于 auto 参数,这还不起作用。) std::bind 是否有任何其他有效用例击败 C++ lambdas 替代方案或者 std::用C++14绑定(bind)多余?

最佳答案

Scott Meyers 给出了 talk对这个。这是我记得的:

在 C++14 中,没有什么有用的绑定(bind)可以做,而 lambdas 也不能做。

在 C++11 中,有些事情不能用 lambdas 完成:

  1. 在创建 lambda 时,您不能在捕获时移动变量。变量总是被捕获为左值。对于绑定(bind),您可以编写:

    auto f1 = std::bind(f, 42, _1, std::move(v));
    
  2. 无法捕获表达式,只有标识符可以。对于绑定(bind),您可以编写:

    auto f1 = std::bind(f, 42, _1, a + b);
    
  3. 函数对象的重载参数。这已经在问题中提到了。

  4. 不可能完美地提出论点

在 C++14 中,所有这些都是可能的。

  1. 移动示例:

    auto f1 = [v = std::move(v)](auto arg) { f(42, arg, std::move(v)); };
    
  2. 表达式示例:

    auto f1 = [sum = a + b](auto arg) { f(42, arg, sum); };
    
  3. 查看问题

  4. 完美转发:可以写

    auto f1 = [=](auto&& arg) { f(42, std::forward<decltype(arg)>(arg)); };
    

bind的一些缺点:

  • Bind 按名称绑定(bind),因此如果您有多个具有相同名称的函数(重载函数),则 bind 不知道使用哪一个。以下示例无法编译,而 lambdas 不会有问题:

    void f(int); void f(char); auto f1 = std::bind(f, _1, 42);
    
  • 使用绑定(bind)函数时不太可能被内联

另一方面,从理论上讲,lambda 可能会生成比绑定(bind)更多的模板代码。因为对于每个 lambda,你都会得到一个唯一的类型。对于绑定(bind),只有当你有不同的参数类型和不同的函数时(我猜在实践中,你用相同的参数和函数绑定(bind)多次并不会经常发生)。

Jonathan Wakely 在他的回答中提到的实际上是不使用绑定(bind)的另一个原因。我不明白你为什么要默默地忽略参数。

关于c++ - 为什么在 C++14 中使用 std::bind 而不是 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17363003/

相关文章:

c++ - 编译器方差 : type of `this` when value-captured in mutable lambda defined in a const member function

c++ - 如何从预定义常量中获取#define 符号而不是值

c++ - 我如何获取字符串输入,将其用每个空格隔开,并将每个单词放入数组,然后对单个单词进行检查?

c++ - boost::thread_specific_ptr 无法访问类中声明的私有(private)成员

python - Tkinter lambda 函数

sockets - HAProxy 无法启动,无法绑定(bind) UNIX 套接字 [/run/haproxy/admin.sock]

c++ - 为什么 libstdc++ 为迭代器上的二元运算符实现 <L,R> 和 <LR> 重载?

c# - 动态改变lambda表达式的主体?

c++ - 使用 Boost lambda 和绑定(bind)排序时出错

javascript - 在初始点击事件 (A) 之后绑定(bind)点击事件 (B) 会导致事件 B 立即触发