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

模板编程:

  1. #include <iostream>
  2. using namespace std;
  3. //未使用函数包装器
  4. template <typename T,typename F>
  5. T use_f(T v, F f)
  6. {
  7. static int count = ;
  8. count++;
  9. cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
  10. return f(v);
  11. }
  12. class Fp
  13. {
  14. private:
  15. double z_;
  16. public:
  17. Fp(double z = 1.0):z_(z){}
  18. double operator ()(double p) {return z_*p;}
  19. };
  20. class Fq
  21. {
  22. private:
  23. double z_;
  24. public:
  25. Fq(double z = 1.0):z_(z){}
  26. double operator ()(double p) {return z_+p;}
  27. };
  28. double dub(double x){return 2.0*x;}
  29. double square(double x){return x*x;}
  30. int main(int argc, char *argv[])
  31. {
  32. double y = 1.2;
  33. cout<<"Function pointer dub:"<<endl;
  34. cout<<" --"<<use_f(y,dub);
  35. cout<<"Function pointer square:"<<endl;
  36. cout<<" --"<<use_f(y,square);
  37. cout<<"Function pointer Fp:"<<endl;
  38. cout<<" --"<<use_f(y,Fp());
  39. cout<<"Function pointer Fq:"<<endl;
  40. cout<<" --"<<use_f(y,Fq());
  41. cout<<"Function pointer lambada1:"<<endl;
  42. cout<<" --"<<use_f(y,[](double u){return u*u;});
  43. cout<<"Function pointer lambada2:"<<endl;
  44. cout<<" --"<<use_f(y,[](double u){return u+2.5;});
  45. return ;
  46. }

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

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

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

  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. //使用函数包装器
  5. template <typename T,typename F>
  6. T use_f(T v, F f)
  7. {
  8. static int count = ;
  9. count++;
  10. cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
  11. return f(v);
  12. }
  13. class Fp
  14. {
  15. private:
  16. double z_;
  17. public:
  18. Fp(double z = 1.0):z_(z){}
  19. double operator ()(double p) {return z_*p;}
  20. };
  21. class Fq
  22. {
  23. private:
  24. double z_;
  25. public:
  26. Fq(double z = 1.0):z_(z){}
  27. double operator ()(double p) {return z_+p;}
  28. };
  29. double dub(double x){return 2.0*x;}
  30. double square(double x){return x*x;}
  31. int main(int argc, char *argv[])
  32. {
  33. double y = 1.2;
  34. // cout<<"Function pointer dub:"<<endl;
  35. // cout<<" --"<<use_f(y,dub);
  36. // cout<<"Function pointer square:"<<endl;
  37. // cout<<" --"<<use_f(y,square);
  38. // cout<<"Function pointer Fp:"<<endl;
  39. // cout<<" --"<<use_f(y,Fp());
  40. // cout<<"Function pointer Fq:"<<endl;
  41. // cout<<" --"<<use_f(y,Fq());
  42. // cout<<"Function pointer lambada1:"<<endl;
  43. // cout<<" --"<<use_f(y,[](double u){return u*u;});
  44. // cout<<"Function pointer lambada2:"<<endl;
  45. // cout<<" --"<<use_f(y,[](double u){return u+2.5;});
  46. std::function<double(double)> fdub = dub;
  47. std::function<double(double)> fsquare = square;
  48. std::function<double(double)> fFp = Fp();
  49. std::function<double(double)> fFq = Fq();
  50. std::function<double(double)> lambada1 = [](double u){return u*u;};
  51. std::function<double(double)> lambada2 = [](double u){return u+2.5;};
  52. cout<<"Function pointer dub:"<<endl;
  53. cout<<" --"<<use_f(y,fdub);
  54. cout<<"Function pointer square:"<<endl;
  55. cout<<" --"<<use_f(y,fsquare);
  56. cout<<"Function pointer Fp:"<<endl;
  57. cout<<" --"<<use_f(y,fFp);
  58. cout<<"Function pointer Fq:"<<endl;
  59. cout<<" --"<<use_f(y,fFq);
  60. cout<<"Function pointer lambada1:"<<endl;
  61. cout<<" --"<<use_f(y,lambada1);
  62. cout<<"Function pointer lambada2:"<<endl;
  63. cout<<" --"<<use_f(y,lambada2);
  64. return ;
  65. }

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

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

熊掌与鱼:

  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. //模板中使用函数包装器
  5. template <typename T>
  6. T use_f(T v, std::function<T(T)> f)
  7. {
  8. static int count = ;
  9. count++;
  10. cout<<"use_f count = "<<count<<": &count"<<&count<<endl;
  11. return f(v);
  12. }
  13. class Fp
  14. {
  15. private:
  16. double z_;
  17. public:
  18. Fp(double z = 1.0):z_(z){}
  19. double operator ()(double p) {return z_*p;}
  20. };
  21. class Fq
  22. {
  23. private:
  24. double z_;
  25. public:
  26. Fq(double z = 1.0):z_(z){}
  27. double operator ()(double p) {return z_+p;}
  28. };
  29. double dub(double x){return 2.0*x;}
  30. double square(double x){return x*x;}
  31. int main(int argc, char *argv[])
  32. {
  33. double y = 1.2;
  34. //这里需要<double>使得std::function<T(T)>实例化为具体的对象
  35. cout<<"Function pointer dub:"<<endl;
  36. cout<<" --"<<use_f<double>(y,&dub);
  37. cout<<"Function pointer square:"<<endl;
  38. cout<<" --"<<use_f<double>(y,square);
  39. cout<<"Function pointer Fp:"<<endl;
  40. cout<<" --"<<use_f<double>(y,Fp());
  41. cout<<"Function pointer Fq:"<<endl;
  42. cout<<" --"<<use_f<double>(y,Fq());
  43. cout<<"Function pointer lambada1:"<<endl;
  44. cout<<" --"<<use_f<double>(y,[](double u){return u*u;});
  45. cout<<"Function pointer lambada2:"<<endl;
  46. cout<<" --"<<use_f<double>(y,[](double u){return u+2.5;});
  47. return ;
  48. }

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

使用std::function改善模板的低效性的更多相关文章

  1. 用lambda表达式和std::function类模板改进泛型抽象工厂设计

  2. 剖析std::function接口与实现

    目录 前言 一.std::function的原理与接口 1.1 std::function是函数包装器 1.2 C++注重运行时效率 1.3 用函数指针实现多态 1.4 std::function的接 ...

  3. C++11中的std::function

    看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::fun ...

  4. 【转】C++11中的std::function

    原文地址:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard: ...

  5. 第12课 std::bind和std::function(3)_std::function可调用对象包装器

    1. std::function (1)首先是一个类模板,用于包装可调用对象.可以容纳除了类成员(函数)指针之外的所有可调用对象. (2)可以将普通函数,lambda表达式和函数对象类统一起来.尽管它 ...

  6. 第10课 std::bind和std::function(1)_可调用对象

    1. 几种可调用对象(Callable Objects) (1)普通函数指针或类成员的函数指针 (2)具有operator()成员函数的类对象(仿函数).如c++11中的std::function类模 ...

  7. std::function介绍 -转载

    类模版std::function是一种通用.多态的函数封装.std::function的实例可以对任何可以调用的目标实体进行存储.复制.和调用操作,这些目标实体包括普通函数.Lambda表达式.函数指 ...

  8. callable object与新增的function相关 C++11中万能的可调用类型声明std::function<...>

    在c++11中,一个callable object(可调用对象)可以是函数指针.lambda表达式.重载()的某类对象.bind包裹的某对象等等,有时需要统一管理一些这几类对象,新增的function ...

  9. C++11 std::function用法

    转自 http://www.hankcs.com/program/cpp/c11-std-function-usage.html function可以将普通函数,lambda表达式和函数对象类统一起来 ...

随机推荐

  1. PAT(B) 1012 数字分类(Java)

    题目链接:1012 数字分类 代码 /** * Score 20 * Run Time 142ms * @author wowpH * @version 1.1 */ import java.util ...

  2. diy操作系统 附录:常用命令

    ld -m elf_i386 as --32 gcc -m 16 o

  3. css 背景 background

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! background我们一般用到的的属性有: background-attachment:背景(图片)是否 ...

  4. 怎样确保页面中的js代码一定是在DOM结构生成之后再调用

    有这样一类问题, 如下所示, 就是在dom结构没有生成时就在js代码中调用了, 此时就会报错: <head> <script> console.log(document.bod ...

  5. UnityC#中修改RectTransform

    1.改变RectTransform的Left和Buttom GetComponent<RectTransform>().offsetMax = new Vector2(left, top) ...

  6. restTemplate源码解析(四)执行ClientHttpRequest请求对象

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们创建了一个ClientHttpRequest的实例.本文将继续阅读Cl ...

  7. ORACLE 存储过程提高

    1.SQLCODE和SQLERRM 2.%TYPE和%ROWTYPE的使用 3.sql%rowcount的作用 1.SQLCODE和SQLERRM SQLCode:数据库操作的返回码,其中 --成功: ...

  8. 【appium】appium中的元素定位和基本操作

    # coding=utf-8 from appium import webdriver import time from selenium.webdriver.support.ui import We ...

  9. django 常用 详解

    Django 1 django框架介绍 是一个开源框架,2005年发布,采用Python语言编写的,早期时主要做新闻和内容管理的网站 Django本身提供了非常强大的后台管理系统 看中文说明文档 百度 ...

  10. Django drf:认证及组件、token、局部钩子源码分析

    一.drf认证功能 二.token讲解 三.局部钩子源码分析 一.drf认证功能 1.认证简介: 只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录则不能查 ...