zoukankan      html  css  js  c++  java
  • 关于虚函数及其替代方式效率对比

    这个可以参考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;

    }

       

  • 相关阅读:
    16进制与10进制
    npm模块管理器
    Vue2+VueRouter2+webpack 构建项目实战(四)接通api,先渲染个列表
    cross-env使用笔记
    webpack 运行提示“The ‘mode‘ option has not been set”的原因和解决方法
    cnpm install -S 与cnpm install -D (dependencies和devDependencies的区别)
    Webpack基础学习
    webpack入门——webpack的安装与使用
    npm init 之package.json
    入门 Webpack,看这篇就够了
  • 原文地址:https://www.cnblogs.com/rocketfan/p/4520069.html
Copyright © 2011-2022 走看看