关于虚函数及其替代方式效率对比

这个可以参考effective c++

http://www.cppblog.com/tiandejian/archive/2011/12/25/epp_35.html

   

这里给出一个测试程序 对比了3种不同实现方案的效率,这三种方案的效果是等价的

1.使用虚函数

2.使用std::function

3.使用模板的trick

template<typename Derived> class Base; class A : public Base<A>; 使用Derived::..

这里特别注意这个tric能够在保证效率的同时能保持继承多态

 这个设计非常有用 把核心的多次调用代码设计为非虚函数,而外层是虚函数保持动态多态特性,在性能和灵活性最好的折中。

不过问题是似乎没办法处理非static

 

当然模板方法效率最高,比较奇怪的是std::function效率最低,而虚函数其实代价很小,10000000也就是1000万的调用也只有多出不到0.02s

结论:

1.除非极端需要效率虚函数是最好最优雅简单的实现方式

2.极端需要效率考虑使用模板tric

3.std::function最灵活 一般不需要考虑使用,考虑写法会麻烦一些 同时效率较低 当然也效率一般也降低的不是太多

一般来说除非极端情况都不会是效率瓶颈

   

./test_derive

I0521 16:10:00.118948 23283 test_derive.cc:98] A deal

I0521 16:10:00.119071 23283 test_derive.cc:58] base func

I0521 16:10:00.119079 23283 test_derive.cc:103] A func

I0521 16:10:00.119086 23283 test_derive.cc:103] A func

I0521 16:10:00.119091 23283 test_derive.cc:117] B deal

I0521 16:10:00.119096 23283 test_derive.cc:58] base func

I0521 16:10:00.119101 23283 test_derive.cc:122] B func

I0521 16:10:00.119106 23283 test_derive.cc:122] B func

I0521 16:10:00.699487 23283 time_util.h:141] std::function using: [580.364 ms] (0.580362 s)

I0521 16:10:00.852361 23283 time_util.h:141] virutal using: [152.82 ms] (0.152819 s)

I0521 16:10:00.992095 23283 time_util.h:141] template using: [139.72 ms] (0.139718 s)

   

   

/**

* ==============================================================================

*

* \file test_derive.cc

*

* \author chenghuige

*

* \date 2015-05-21 15:01:54.463482

*

* \Description:

*

* ==============================================================================

*/

   

#define private public

#define protected public

#include "common_util.h"

   

using namespace std;

using namespace gezi;

   

DEFINE_int32(vl, 0, "vlog level");

DEFINE_int32(level, 0, "min log level");

DEFINE_string(type, "simple", "");

DEFINE_bool(perf, false, "");

DEFINE_int32(num, 1, "");

DEFINE_string(i, "", "input file");

DEFINE_string(o, "", "output file");

   

class IBase

{

public:

virtual void eval() = 0;

virtual void speed_virtual() = 0;

virtual void speed_template() = 0;

virtual void speed_function() = 0;

};

   

template<typename Derived>

class Base : public IBase

{

public:

virtual void eval() override

{

deal();

func();

Derived::func();

_func();

}

   

virtual void deal()

{

VLOG(0) << "base deal";

}

   

static void func()

{

VLOG(0) << "base func";

}

   

   

virtual void speed_virtual() override

{

for (size_t i = 0; i < 10000000; i++)

{

deal();

}

}

   

virtual void speed_template() override

{

for (size_t i = 0; i < 10000000; i++)

{

Derived::func();

}

}

   

virtual void speed_function()

{

for (size_t i = 0; i < 10000000; i++)

{

_func();

}

}

   

std::function<void()> _func;

};

   

class A : public Base < A >

{

public:

A()

{

_func = A::func;

}

virtual void deal()

{

VLOG(0) << "A deal";

}

   

static void func()

{

VLOG(0) << "A func";

}

};

   

   

class B : public Base < B >

{

public:

B()

{

_func = B::func;

}

virtual void deal()

{

VLOG(0) << "B deal";

}

   

static void func()

{

VLOG(0) << "B func";

}

};

   

void run()

{

shared_ptr<IBase> a = make_shared<A>();

shared_ptr<IBase> b = make_shared<B>();

a->eval();

b->eval();

}

   

void run_perf()

{

FLAGS_v = -1;

shared_ptr<IBase> a = make_shared<A>();

shared_ptr<IBase> b = make_shared<B>();

{

Notifer nt("std::function", -1);

a->speed_function();

b->speed_function();

}

{

Notifer nt("virutal", -1);

a->speed_virtual();

b->speed_virtual();

}

{

Notifer nt("template", -1);

a->speed_template();

b->speed_template();

}

}

   

int main(int argc, char *argv[])

{

google::InitGoogleLogging(argv[0]);

google::InstallFailureSignalHandler();

google::SetVersionString(get_version());

int s = google::ParseCommandLineFlags(&argc, &argv, false);

if (FLAGS_log_dir.empty())

FLAGS_logtostderr = true;

FLAGS_minloglevel = FLAGS_level;

//LogHelper::set_level(FLAGS_level);

if (FLAGS_v == 0)

FLAGS_v = FLAGS_vl;

   

run();

   

run_perf();

   

return 0;

}

   

posted @ 2015-05-21 16:23  阁子  阅读(1875)  评论(0编辑  收藏  举报