C++11有了lambda后bind还有多大意义?

lambda 是语言层面的 feature,功能强大,性能高,而 bind 在很多时候使用起来更简洁。

在现实中,至少有一种情况,一定不要使用 bind:把 lambda 当作 std::function 使用时!

在 MySQL 源码中,有这样一段代码:

void handler::ha_statistic_increment(ulonglong System_status_var::*offset) const {
  if (table && table->in_use) {
    (table->in_use->status_var.*offset)++;
    table->in_use->check_limit_rows_examined();
    table->in_use->update_sql_stats_periodic();
    table->in_use->check_yield(std::bind(yield_condition, table));
  }
}

注意其中使用的 std::bind

table->in_use->check_yield(std::bind(yield_condition, table));

这个 bind 以最简洁的方式,非常准确直观地表达了程序意图,我们看 yield_condition 的原型:

static bool yield_condition(TABLE*);

它只有一个参数,而 check_yield 函数是这样的:

void THD::check_yield(std::function<bool()> cond) {...}

上面的 std::bind 会生成一个 class,其实现了 operator(),仅针对这个例子,实例化之后大致会是这样:

struct BindType {
   bool (*m_yield_condition)(TABLE*); // = &yield_condition
   TABLE* m_table; // = table;
   bool operator() const { return m_yield_condition(m_table); }
};

可以看到,BindType 至少需要占用两个指针的空间,记住这一点!

std::function 的实现,一般(g++ 的 libstdc++)占用四个指针的空间,如果用来初始化 std::function 的 Functor 对象(包括函数指针、lambda……)尺寸过大,就需要通过 new 在堆上申请内存,用来保存 Functor。

MySQL 的这个 std::bind,就生成了一个让 std::function 必须 new 内存的 Functor!这个额外的消耗,在火焰图中虽然占比不多,但还是清晰可见的:

虽然这个总耗时不多,但是看看 new/delete 占了多大比例!当然,这个问题,只要意识到了,改进修复还是非常简单的,使用 lambda 即可:

这个 lambda 仅捕获了 handler::table,当然也可以改成这样:

[this]() { return yield_condition(this->table); }

但是捕获 table 性能要更高,因为此刻编译器早已把 table 成员加载到某个寄存器中了,从而需要的后续操作更少。

这个 lambda 的尺寸只有一个指针大小,用它来构造 std::function,不需要 new/delete!

如果 lambda 的尺寸无论如何都超过一个指针大小呢?

使用 std::ref,这样写:

auto lambda = [...](...) {...}; // 超过一个指针大小的 lambda
std::function<...> func(std::ref(lambda));
// ...

但这个前提是必须保证 lambda 的生命周期覆盖 func

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值