• 使用std::function改善模板的低效性


    泛型编程中,模板会根据传入类型的不同,生成多种实例,相对低效。

    模板编程:

    #include <iostream>
    
    using namespace std;
    
    //未使用函数包装器
    template <typename T,typename F>
    T use_f(T v, F f)
    {
        static int count = 0;
        count++;
        cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
        return f(v);
    }
    
    
    class Fp
    {
    private:
        double z_;
    public:
        Fp(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_*p;}
    };
    
    
    class Fq
    {
    private:
        double z_;
    public:
        Fq(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_+p;}
    };
    
    double dub(double x){return 2.0*x;}
    double square(double x){return x*x;}
    
    
    int main(int argc, char *argv[])
    {
        double y = 1.2;
        cout<<"Function pointer dub:"<<endl;
        cout<<" --"<<use_f(y,dub);
        cout<<"Function pointer square:"<<endl;
        cout<<" --"<<use_f(y,square);
        cout<<"Function pointer Fp:"<<endl;
        cout<<" --"<<use_f(y,Fp());
        cout<<"Function pointer Fq:"<<endl;
        cout<<" --"<<use_f(y,Fq());
        cout<<"Function pointer lambada1:"<<endl;
        cout<<" --"<<use_f(y,[](double u){return u*u;});
        cout<<"Function pointer lambada2:"<<endl;
        cout<<" --"<<use_f(y,[](double u){return u+2.5;});
        return 0;
    }

     模板编程的优势是高度抽象,将算法统一封装,但是其根据类型实例化的特性也造成了其低效性。

     以上执行结果,通过查看静态模板函数中,静态数据的地址,其产生了5个函数实例。代码量受传入类型的影响产生了巨大的增量。

    通过std::function来减少模板的实例化:

    #include <iostream>
    #include <functional>
    using namespace std;
    
    //使用函数包装器
    template <typename T,typename F>
    T use_f(T v, F f)
    {
        static int count = 0;
        count++;
        cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
        return f(v);
    }
    
    
    class Fp
    {
    private:
        double z_;
    public:
        Fp(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_*p;}
    };
    
    
    class Fq
    {
    private:
        double z_;
    public:
        Fq(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_+p;}
    };
    
    double dub(double x){return 2.0*x;}
    double square(double x){return x*x;}
    
    
    int main(int argc, char *argv[])
    {
        double y = 1.2;
        //    cout<<"Function pointer dub:"<<endl;
        //    cout<<" --"<<use_f(y,dub);
        //    cout<<"Function pointer square:"<<endl;
        //    cout<<" --"<<use_f(y,square);
        //    cout<<"Function pointer Fp:"<<endl;
        //    cout<<" --"<<use_f(y,Fp());
        //    cout<<"Function pointer Fq:"<<endl;
        //    cout<<" --"<<use_f(y,Fq());
        //    cout<<"Function pointer lambada1:"<<endl;
        //    cout<<" --"<<use_f(y,[](double u){return u*u;});
        //    cout<<"Function pointer lambada2:"<<endl;
        //    cout<<" --"<<use_f(y,[](double u){return u+2.5;});
    
        std::function<double(double)> fdub     = dub;
        std::function<double(double)> fsquare  = square;
        std::function<double(double)> fFp      = Fp();
        std::function<double(double)> fFq      = Fq();
        std::function<double(double)> lambada1 = [](double u){return u*u;};
        std::function<double(double)> lambada2 = [](double u){return u+2.5;};
    
        cout<<"Function pointer dub:"<<endl;
        cout<<" --"<<use_f(y,fdub);
        cout<<"Function pointer square:"<<endl;
        cout<<" --"<<use_f(y,fsquare);
        cout<<"Function pointer Fp:"<<endl;
        cout<<" --"<<use_f(y,fFp);
        cout<<"Function pointer Fq:"<<endl;
        cout<<" --"<<use_f(y,fFq);
        cout<<"Function pointer lambada1:"<<endl;
        cout<<" --"<<use_f(y,lambada1);
        cout<<"Function pointer lambada2:"<<endl;
        cout<<" --"<<use_f(y,lambada2);
    
        return 0;
    }

    所有的静态变量只有一个地址,也就是说模板 函数只产生了一个实例,其类型只需要匹配是一个std::function<double(double)>传入的对象即可,模板的效率大为提高。 

    但是看来好像代码量并未减少甚至还有些许增多,下面我们通过优化来解决这个问题。

    熊掌与鱼:

    #include <iostream>
    #include <functional>
    using namespace std;
    
    //模板中使用函数包装器
    template <typename T>
    T use_f(T v, std::function<T(T)> f)
    {
        static int count = 0;
        count++;
        cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
        return f(v);
    }
    
    
    class Fp
    {
    private:
        double z_;
    public:
        Fp(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_*p;}
    };
    
    
    class Fq
    {
    private:
        double z_;
    public:
        Fq(double z = 1.0):z_(z){}
        double operator ()(double p) {return z_+p;}
    };
    
    double dub(double x){return 2.0*x;}
    double square(double x){return x*x;}
    
    
    int main(int argc, char *argv[])
    {
        double y = 1.2;
        //这里需要<double>使得std::function<T(T)>实例化为具体的对象
        cout<<"Function pointer dub:"<<endl;
        cout<<" --"<<use_f<double>(y,&dub);
        cout<<"Function pointer square:"<<endl;
        cout<<" --"<<use_f<double>(y,square);
        cout<<"Function pointer Fp:"<<endl;
        cout<<" --"<<use_f<double>(y,Fp());
        cout<<"Function pointer Fq:"<<endl;
        cout<<" --"<<use_f<double>(y,Fq());
        cout<<"Function pointer lambada1:"<<endl;
        cout<<" --"<<use_f<double>(y,[](double u){return u*u;});
        cout<<"Function pointer lambada2:"<<endl;
        cout<<" --"<<use_f<double>(y,[](double u){return u+2.5;});
    
    
    
        return 0;
    }

     实例化与代码量都减少了,鱼和熊掌兼得。

     

  • 相关阅读:
    学了N年英语,你学会翻译了吗?——最基本的数据库连接
    混编,还是会犯错~
    call dword prt[eax]
    时间复杂度和空间复杂度1 数据结构和算法03
    call dword prt[eax+5]
    地址反向增长(栈底为大地址,栈顶为小地址)
    OD使用教程3(上) 调试篇03|解密系列
    call dword prt[eax+5]
    时间复杂度和空间复杂度1 数据结构和算法03
    call dword prt[eax]
  • 原文地址:https://www.cnblogs.com/wangkeqin/p/11946255.html
Copyright © 2020-2023  润新知