在 C++11 之前,我经常使用 boost::bind
或 boost::lambda
。 bind
部分进入标准库(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 完成:
在创建 lambda 时,您不能在捕获时移动变量。变量总是被捕获为左值。对于绑定(bind),您可以编写:
auto f1 = std::bind(f, 42, _1, std::move(v));
无法捕获表达式,只有标识符可以。对于绑定(bind),您可以编写:
auto f1 = std::bind(f, 42, _1, a + b);
函数对象的重载参数。这已经在问题中提到了。
- 不可能完美地提出论点
在 C++14 中,所有这些都是可能的。
移动示例:
auto f1 = [v = std::move(v)](auto arg) { f(42, arg, std::move(v)); };
表达式示例:
auto f1 = [sum = a + b](auto arg) { f(42, arg, sum); };
查看问题
完美转发:可以写
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/