C++ Pirate: Lambda vs Bind (一)

2014-11-23 22:54:04 · 作者: · 浏览: 21
Lambda 与 Bind的性能比较
先让我们看看下面函数:
[cpp]
template
void do_test_loop(Function func, const uint64_t upper_limit = 1000000000ULL)
{
for (uint64_t i = 0; i < upper_limit; ++i)
func(i);
}
template
void do_test_loop(Function func, const uint64_t upper_limit = 1000000000ULL)
{
for (uint64_t i = 0; i < upper_limit; ++i)
func(i);
}
该函数只是简单对func函数做upper_limit(默认10亿次)次循环调用。有很多种方法给被反复调用的函数func传入实际参数,在这里我们只讨论两种: 1. 使用std::bind来生成一个多态的std::function函数。 2.lambda表达式
[cpp]
void test_accumulate_bind_function(uint64_t& x, uint64_t i)
{
x += i;
}
uint64_t test_accumulate_bind()
{
namespace arg = std::placeholders;
uint64_t x = 0;
std::function
accumulator = std::bind(&test_accumulate_bind_function,
std::ref(x), arg::_1);
do_test_loop(accumulator);
return x;
}
void test_accumulate_bind_function(uint64_t& x, uint64_t i)
{
x += i;
}
uint64_t test_accumulate_bind()
{
namespace arg = std::placeholders;
uint64_t x = 0;
std::function accumulator = std::bind(&test_accumulate_bind_function, std::ref(x), arg::_1);
do_test_loop(accumulator);
return x;
} 这是一个简单的函数,在使用boost::bind函数时,我所遇到的最大的问题是它需要你将函数和逻辑分离,这样会导致难以理解的代码。对比较大的函数来说,这并不是什么大问题,但是对于小函数来说运行时的上下文切换将会很耗时(令人讨厌),例如上面所列举的函数。 与上述函数相同的lambda表达式如下:
[cpp]
uint64_t test_accumulate_lambda() {
uint64_t x = 0;
auto accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x; } uint64_t test_accumulate_lambda()
{
uint64_t x = 0;
auto accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
lambda表达式没有运行时的上下文切换。当然,我们也因此失去了std::function所具有的高级的多态特性。lambda是一种由编译器静态关联的无名类型,这也是为什么在定义该类型时必须使用auto关键字的原因。变量accumulator表示lambda表达式的结果(没有其他的lambda表达式能生成与此一样的结果)。即使是两个内容差不多的表达式也不会有相同的类型。如果do_test_loop是一个在cpp文件中实现的函数,那么我们将在其的作用域范围内获取不到传入进来的lambda表达式类型。 幸运的是,有些聪明的人已考虑到了这个潜在的问题,并且由一个lambda表达式赋值给一个std::function类型不仅仅是可能的,而且还是极其容易的:
[cpp]
uint64_t test_accumulate_bound_lambda() {
uint64_t x = 0;
std::function accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x; } uint64_t test_accumulate_bound_lambda()
{
uint64_t x = 0;
std::function accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
} 通过使用 lambda语义来替代std::bind,我们获取到了std::function多态的所有威力和C++ lambda表达式所拥有的便利和高性能表现。这听起来像是一种双赢。 对于这三个函数我们可以做个简单的比较(使用timer类):
[cpp]
template
void run_test(const std::string& name,
timer t; volatile_write(func());
timer::duration duration = t.elapsed();
std::cout << '\t' << duration.count() << std::endl;
} int main() { run_test("Accumulate (lambda)
", &test_accumulate_lambda);
run_test("Accumulate (bind)
", &test_accumulate_bind);
run_test("Accumulate (bound lambda)"
, &test_accumulate_bound_lambda);
} template
void run_test(const std::string& name, Function func)
{
std::cout << name;
timer t;
volatile_write(func());
timer::duration duration = t.elapsed();
std::cout << '\t' << duration.count() << std::endl;
}
int main()
{
run_test("Accumulate (lambda) ", &test_