何时应该使用std::bind?

39
每次我需要使用 std::bind时,最终都会使用lambda表达式。那么,在什么情况下应该使用 std::bind呢?最近我刚从一个代码库中删除了它,发现与 std::bind 相比,lambda 表达式始终更简单、更清晰。 std::bind 完全是不必要的吗?它未来是否应该被弃用?在什么情况下应该优先考虑使用 std::bind 而不是 lambda 表达式?(它与 lambda 同时加入标准,一定有其原因)。
我还注意到,越来越多的人熟悉lambda表达式(因此他们知道lambda表达式的作用)。然而,很少有人熟悉 std::bindstd::placeholders

1
可能是[Bind Vs Lambda?](https://dev59.com/THI-5IYBdhLWcg3wSGQB)的重复问题。 - Jonathan Wakely
请查看stackoverflow.com/a/17545183/1274850。 - BertR
2个回答

32

这是一个 lambda 函数无法做到的事情:

std::unique_ptr<SomeType> ptr = ...;
return std::bind(&SomeType::Function, std::move(ptr), _1, _2);

对于 Lambdas,它不能捕获移动语义类型;它只能通过复制或左值引用来捕获值。尽管这是一个暂时的问题,正在积极为 C++14 解决😉

"更简单和更清晰" 是一种观点。对于简单绑定情况,bind 所需的输入更少。而且,bind 仅关注函数绑定,因此如果您看到 std::bind,就知道您正在查看什么。而如果您使用 Lambda,则必须查看 Lambda 实现才能确定其功能。

最后,C++ 并不会仅仅因为有其他功能可以实现它的功能就将其废弃。例如,auto_ptr 被废弃是因为它具有固有的危险性,并且有一种非危险的替代方案。


4
似乎在Scott Meyers即将出版的书《Effective C++11》中有一条内容:“更喜欢使用lambda表达式而不是std::bind”。我无法详细评论此事,但如果您愿意,请分享您的见解。 - Andy Prowl
感谢您提供如此出色的答案!这里有一篇关于移动捕获的文章:http://marcoarena.wordpress.com/2012/11/01/learn-how-to-capture-by-move/ 希望我们能在下一个标准中得到真正的移动捕获。 - gnzlbg
6
C++-14将修复lambda的这个不足。 - David Schwartz
6
@AndyProwl,你引用的书中最适用的是这句简短的话:“……自C++14以来,[std::bind]就没有好的使用案例了。” - Drew Dormann
1
虽然我认为,使用C++14,你可能完全可以用lambda表达式来替代std::bind(而且我大多数情况下都这样做),但我仍然喜欢你提到的std::bind功能较弱,因此更清晰地表达了意图。 - MikeMB

24

您可以使用std::bind创建多态对象,而使用lambda表达式无法实现。换句话说,std::bind返回的调用包装器可以使用不同的参数类型进行调用:

#include <functional>
#include <string>
#include <iostream>

struct Polly
{
  template<typename T, typename U>
    auto operator()(T t, U u) const -> decltype(t + u)
    { return t + u; }
};

int main()
{
  auto polly = std::bind(Polly(), std::placeholders::_1, "confusing");

  std::cout << polly(4) << polly(std::string(" this is ")) << std::endl;    
}

我将这个作为puzzle而不是优秀代码的例子创建,但它展示了多态调用包装器。

17
在C++14中,这等同于绑定表达式:[p = Polly{}](auto t) { return p(t, "confusing"); } - Jonathan Wakely
1
@Elliot的operator()显然是const的,所以我不知道你的意思。问题中的代码编译良好,我的第一条评论中的lambda表达式也是如此。 - Jonathan Wakely
抱歉,我犯了一个愚蠢的错误,忘记加上 const。在发表评论之前应该认真检查。 - Elliott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接