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);
    }
}
时间: 2024-09-20 06:17:58

C++中几种callable实现方式的性能对比的相关文章

ArrayList和LinkedList的几种循环遍历方式及性能对比分析

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解. 阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性

HashMap循环遍历方式及其性能对比

主要介绍HashMap的四种循环遍历方式,各种方式的性能测试对比,根据HashMap的源码实现分析性能结果,总结结论. 1. Map的四种遍历方式 下面只是简单介绍各种遍历示例(以HashMap为例),各自优劣会在本文后面进行分析给出结论. (1) for each map.entrySet() Java 1 2 3 4 5 Map<String, String> map = new HashMap<String, String>(); for (Entry<String,

C# 中,有多少种查询的方式?

问题描述 C#中,有多少种查询的方式?Dbadepter,Dbcommand,LoadSet()... 解决方案 解决方案二:还有可以用框架的,如Grove解决方案三:不知道,学习!!

详解JS几种变量交换方式以及性能分析对比_javascript技巧

前言 "两个变量之间的值得交换",这是一个经典的话题,现在也有了很多的成熟解决方案,本文主要是列举几种常用的方案,进行大量计算并分析对比. 起由 最近做某个项目时,其中有一个需求是交换数组中的两个元素.当时使用的方法是: arr = [item0,item1,...,itemN]; //最初使用这段代码来交换第0个和第K(k<N)个元素 arr[0] = arr.splice(k, 1, arr[0])[0]; 当时觉得这种方法很优雅,高逼格... 后来,业余时间又拿这个研究下了

java中四种操作xml方式的比较

xml|比较   1. 介绍 1)DOM(JAXP Crimson解析器)         DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的.DOM以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还

【SSH系列】深入浅出spring IOC中三种依赖注入方式

spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,小编的脑袋中全是大大的问号,不过没有关系,今天这篇博文,小编主要来简单的介绍一下在spring IOC中依赖注入的方法. 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性.我们可以从以下几个方面理解: a.参与者都

MySQL中三种关联查询方式的简单比较_Mysql

看看下面三个关联查询的 SQL 语句有何区别?   SELECT * FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) SELECT * FROM film JOIN film_actor USING (film_id) SELECT * FROM film, film_actor WHERE film.film_id = film_actor.film_id 最大的不同更多是语法糖,但有一些有意思的东西值得关注.

网赚中五种免费赚钱方式 绝对有效

中介交易 SEO诊断 淘宝客 云主机 技术大厅 很多人都在问,到底怎么赚钱,赚钱的最好方法是什么?我感觉最好的赚钱方法是一下:最好的赚钱方法是努力学习,努力工作.下面我们介绍5种免费网赚的方法,只要你能真正的掌握其中一种,并且能坚定决心做下去,我想你会有不菲的收入! 一.最好的赚钱方法是在网上开一个免费网店 如今互联网已经走进千家万户,网络也给人们带来了极大的方便.以前我们想买一样东西,要跑商场,要跑商店,后来开始流行电视购物,如今网络走进千家万户,人们开始网上购物,网上购物给人们带来了很多的方

C#中三种截屏方式总结

昨天写自动化测试的CASE的时候,碰到一个疑难杂症,调用截图的函数去截取一个Popup窗口,但是总是把背景程序给截下来,Popup窗口就跟看不到一样.本来以为是同步的问题,也就是以为先截图再点击弹出Popup窗口了.后来加了N个Thread.Sleep来测试,发现根本不是因为这个原因,而是截图的函数截不下来这个窗口. 这个为啥呢,只好把截图的函数代码翻出来看,以前是用这种方式的: BitBlt(dcImage, 0, 0, (int)(rect.Width), (int)(rect.Height