绑定与Lambda?

我有一个关于哪种风格是首选的问题:std :: bind Vs lambda in C ++ 0x。 我知道他们服务于某些不同的目的,但让我们举一个相交function的例子。

使用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); 

我们应该select哪一个? 为什么? 假设比上述例子更复杂的情况。 ie一个人的优点和缺点是什么?

正如你所说,绑定和lambda不完全是针对同一个目标。

例如,对于使用和组合STLalgorithm,lambda是明确的赢家,恕我直言。

为了说明这一点,我记得有一个非常有趣的答案,在堆栈溢出问题上,有人问了hex数字的想法(如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中,打开英文单词文件,扫描每个单词并且只用“a”,“b”,“c”,“d”,“e”或“f”字母。

现在,打开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); } ); } 

这仍然有点繁重(主要是因为istream_iterator业务),但比绑定版本更简单:)

C ++ 0x lambdas是单形的,而绑定可以是多态的。 你不能有这样的事情

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

a和b必须有已知的types。 另一方面,tr1 / boost / phoenix / lambda绑定允许你这样做:

 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" 

请注意,typesA和B在这里不是固定的。 只有当f被实际使用时,这两个才会被推断出来。

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

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

使用绑定,即使在这个地方只需要逻辑,也不得不创build一个新的函数/方法/函子。 你需要拿出一个合适的名字,这可能会使代码变得不那么容易理解,因为它可能会让你分裂相关的逻辑。

使用lambda,你可以在lambda中添加新的逻辑(但是如果创build一个新的可调用的话,并不是强制的)。

我觉得这更多的是品味的问题。 快速掌握新技术或熟悉函数式编程的人可能更喜欢使用lambda语法,而更保守的程序员则更愿意使用绑定,因为它更像传统的C ++语法。

这样的一个决定应该和那些愿意遵守守则的人协调,可能是通过多数票。

然而,这并没有改变这个事实,即lambda语法更强大,更清晰。

C ++ 0x lambdas基本上replace绑定。 没有什么可以绑定,你不能重新创build一个简单的包装lambda达到相同的。 一旦lambda支持广泛传播,std :: tr1 :: bind将会去std :: bind1st等等。 这是好的,因为大多数程序员因为某种原因而难以获得约束力。