C++中几种callable实现方式的性能对比

前言

C++中想实现一个callable的对象,通常有四种方式:

  1. std::function:最common的方式,一般会配合std::bind使用。
  2. function pointer:最C的方式,但没办法实现有状态的callable object。
  3. function object:就是重载了operator()的类,C++98的STL中经常用。
  4. lambda expression:不会污染namespace,一般来说编译器内部会实现为一个匿名的function object。

从原理上性能最好的应该是3和4,其次是2,最差的是std::function。下面我们用一小段代码来测试它们的性能。

测试结果

  • 测试机器:15' rMBP。
  • 编译器:Apple LLVM version 8.1.0 (clang-802.0.42)。
  • 编译方式:g++ test.cpp -std=c++14 -O2。
./a.out "std::function"  0.15s user 0.20s system 98% cpu 0.358 total
./a.out "function_pointer"  0.10s user 0.11s system 98% cpu 0.209 total
./a.out "function_object"  0.03s user 0.01s system 92% cpu 0.042 total
./a.out "lambda"  0.03s user 0.01s system 93% cpu 0.042 total

可以看到3和4只要42ms,而相对应的2需要209ms,1需要358ms。这个顺序符合我们的预期,但相差这么多还是比较意外的。

测试程序

#include <iostream>
#include <functional>
#include <vector>
#include <string>
#include <utility>

using namespace std;

template <typename HandlerT = std::function<void (int)>>
class Worker{
public:
    explicit Worker(const HandlerT& handler): mHandler(handler) {}
    void Run(int x) {
        mHandler(x);
    }
private:
    HandlerT mHandler;
};

template <typename HandlerT>
void Test(HandlerT&& h) {
    using WorkerT = Worker<HandlerT>;
    vector<WorkerT> v;
    for (int i = 0; i < 10000000; ++i) {
        v.emplace_back(std::forward<HandlerT>(h));
    }
    int j = 0;
    for (auto& w: v) {
        w.Run(++j);
    }
}

void Func(int x) {
    int y = x + 5;
    y += 3;
}

struct Functor {
    void operator()(int x) const {
        int y = x + 5;
        y += 3;
    }
};

int main(int argc, char** argv) {
    if (argc != 2) {
        cerr << "error input" << endl;
        exit(1);
    }

    string mode{argv[1]};
    if (mode == "std::function") {
        Test(bind(Func, placeholders::_1));
    } else if (mode == "function_pointer") {
        Test(Func);
    } else if (mode == "function_object") {
        Test(Functor{});
    } else if (mode == "lambda") {
        Test([](int x) -> void {int y = x + 5; y += 3;});
    } else {
        cerr << "error mode:" << mode << endl;
        exit(1);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值