当前位置: 首页 > news >正文

在线3d建模网站湘潭网站

在线3d建模网站,湘潭网站,建设局属于哪个部门管,wordpress换背景插件本文以C/C程序为例讲述了程序运行效率的10个简单方法#xff0c;分享给大家供大家参考之用。具体分析如下#xff1a; 对于每一个程序员来说#xff0c;程序的运行效率都是一个值得重视#xff0c;并为之付出努力的问题。但是程序性能的优化也是一门复杂的学问#xff0c;… 本文以C/C程序为例讲述了程序运行效率的10个简单方法分享给大家供大家参考之用。具体分析如下 对于每一个程序员来说程序的运行效率都是一个值得重视并为之付出努力的问题。但是程序性能的优化也是一门复杂的学问需要很多的知识然而并不是每个程序员都具备这样的知识而且论述如何优化程序提高程序运行效率的书籍也很少。但是这并不等于我们可以忽略程序的运行效率下面就介绍一下本人积累的一些简单实用的提高程序运行效率的方法希望对大家有所帮助。 一、尽量减少值传递多用引用来传递参数。 至于其中的原因相信大家也很清楚如果参数是int等语言自定义的类型可能能性能的影响还不是很大但是如果参数是一个类的对象那么其效率问题就不言而喻了。例如一个判断两个字符串是否相等的函数其声明如下 bool Comparestring s1, string s2) bool Compare(string *s1, string *s2) bool Compare(string s1, string s2) bool Compare(const string s1, const string s2) 其中若使用第一个函数值传递则在参数传递和函数返回时需要调用string的构造函数和析构函数两次即共多调用了四个函数而其他的三个函数指针传递和引用传递则不需要调用这四个函数。因为指针和引用都不会创建新的对象。如果一个构造一个对象和析构一个对象的开销是庞大的这就是会效率造成一定的影响。 然而在很多人的眼中指针是一个恶梦使用指针就意味着错误那么就使用引用吧它与使用普通值传递一样方便直观同时具有指针传递的高效和能力。因为引用是一个变量的别名对其操作等同于对实际对象操作所以当你确定在你的函数是不会或不需要变量参数的值时就大胆地在声明的前面加上一个const吧就如最后的一个函数声明一样。 同时加上一个const还有一个好处就是可以对常量进行引用若不加上const修饰符引用是不能引用常量的。 二、i和i引申出的效率问题 看了上面的第一点你可能觉得那不就是多调用了四个函数而已你可能对此不屑一顾。那么来看看下面的例子应该会让你大吃一惊。 至于整型变量的前加和后加的区别相信大家也是很清楚的。然而在这里我想跟大家谈的却是C类的运算符重载为了与整形变量的用法一致在C中重载运算符时一般都会把前加和后加都重载。你可能会说你在代码中不会重载运算符但是你敢说你没有使用过类的运算符重载吗迭代器类你总使用过吧可能到现在你还不是很懂我在说什么那么就先看看下面的例子吧是本人为链表写的一个内部迭代器。 _SingleList::Iterator _SingleList::Iterator::operator()//前加 {pNote pNote-pNext;return *this; } _SingleList::Iterator _SingleList::Iterator::operator(int)//后加 {Iterator tmp(*this);pNote pNote-pNext;return tmp; }从后加的实现方式可以知道对象利用自己创建一个临时对象自己在函数调用的一个复制然后改变自己的状态并返回这个临时对象而前加的实现方式时直接改变自己的内部状态并返回自己的引用。 从第一点的论述可以知道后加实现时会调用复制构造函数在函数返回时还要调用析构函数而由于前加实现方式直接改变对象的内部状态并返回自己的引用至始至终也没有创建新的对象所以也就不会调用构造函数和析构函数。 然而更加糟糕的是迭代器通常是用来遍历容器的它大多应用在循环中试想你的链表有100个元素用下面的两种方式遍历 for(_SingleList::Iterator it list.begin(); it ! list.end(); it) {//do something } for(_SingleList::Iterator it list.begin(); it ! list.end(); it) {//do something } 如果你的习惯不好写了第二种形式那么很不幸做同样的事情就是因为一个前加和一个后加的区别你就要调用多200个函数其对效率的影响可就不可忽视了。 三、循环引发的讨论1循环内定义还是循环外定义对象 请看下面的两段代码 代码1 ClassTest CT for(int i 0; i 100; i) {CT a;//do something }代码2 for(int i 0; i 100; i) {ClassTest CT a;//do something }你会觉得哪段代码的运行效率较高呢代码1科学家是代码2其实这种情况下哪段代码的效率更高是不确定的或者说是由这个类ClassTest本向决定的分析如下 对于代码1需要调用ClassTest的构造函数1次赋值操作函数operator100次对于代码2需要高用复制构造函数100次析构函数100次。 如果调用赋值操作函数的开销比调用构造函数和析构函数的总开销小则第一种效率高否则第二种的效率高。 四、循环引发的讨论2避免过大的循环 现在请看下面的两段代码 代码1 for(int i 0; i n; i) {fun1();fun2(); }代码2 for(int i 0; i n; i) {fun1(); } for(int i 0; i n; i) {fun2(); }注这里的fun1()和fun2()是没有关联的即两段代码所产生的结果是一样的。 以代码的层面上来看似乎是代码1的效率更高因为毕竟代码1少了n次的自加运算和判断毕竟自加运算和判断也是需要时间的。但是现实真的是这样吗 这就要看fun1和fun2这两个函数的规模或复杂性了如果这多个函数的代码语句很少则代码1的运行效率高一些但是若fun1和fun2的语句有很多规模较大则代码2的运行效率会比代码1显著高得多。可能你不明白这是为什么要说是为什么这要由计算机的硬件说起。 由于CPU只能从内存在读取数据而CPU的运算速度远远大于内存所以为了提高程序的运行速度有效地利用CPU的能力在内存与CPU之间有一个叫Cache的存储器它的速度接近CPU。而Cache中的数据是从内存中加载而来的这个过程需要访问内存速度较慢。 这里先说说Cache的设计原理就是时间局部性和空间局部性。时间局部性是指如果一个存储单元被访问则可能该单元会很快被再次访问这是因为程序存在着循环。空间局部性是指如果一个储存单元被访问则该单元邻近的单元也可能很快被访问这是因为程序中大部分指令是顺序存储、顺序执行的数据也一般也是以向量、数组、树、表等形式簇聚在一起的。 看到这里你可能已经明白其中的原因了。没错就是这样如果fun1和fun2的代码量很大例如都大于Cache的容量则在代码1中就不能充分利用Cache了由时间局部性和空间局部性可知因为每循环一次都要把Cache中的内容踢出重新从内存中加载另一个函数的代码指令和数据而代码2则更很好地利用了Cache利用两个循环语句每个循环所用到的数据几乎都已加载到Cache中每次循环都可从Cache中读写数据访问内存较少速度较快理论上来说只需要完全踢出fun1的数据1次即可。 五、局部变量VS静态变量 很多人认为局部变量在使用到时才会在内存中分配储存单元而静态变量在程序的一开始便存在于内存中所以使用静态变量的效率应该比局部变量高其实这是一个误区使用局部变量的效率比使用静态变量要高。 这是因为局部变量是存在于堆栈中的对其空间的分配仅仅是修改一次esp寄存器的内容即可即使定义一组局部变量也是修改一次。而局部变量存在于堆栈中最大的好处是函数能重复使用内存当一个函数调用完毕时退出程序堆栈内存空间被回收当新的函数被调用时局部变量又可以重新使用相同的地址。当一块数据被反复读写其数据会留在CPU的一级缓存Cache中访问速度非常快。而静态变量却不存在于堆栈中。 可以说静态变量是低效的。 六、避免使用多重继承 在C中支持多继承即一个子类可以有多个父类。书上都会跟我们说多重继承的复杂性和使用的困难并告诫我们不要轻易使用多重继承。其实多重继承并不仅仅使程序和代码变得更加复杂还会影响程序的运行效率。 这是因为在C中每个对象都有一个this指针指向对象本身而C中类对成员变量的使用是通过this的地址加偏移量来计算的而在多重继承的情况下这个计算会变量更加复杂从而降低程序的运行效率。而为了解决二义性而使用虚基类的多重继承对效率的影响更为严重因为其继承关系更加复杂和成员变量所属的父类关系更加复杂。 七、尽量少使用dynamic_cast dynamic_cast的作用是进行指针或引用的类型转换dynamic_cast的转换需要目标类型和源对象有一定的关系继承关系。 实现从子类到基类的指针转换实际上这种转换是非常低效的对程序的性能影响也比较大不可大量使用而且继承关系越复杂层次越深其转换时间开销越大。在程序中应该尽量减少使用。 八、减少除法运算的使用 无论是整数还是浮点数运算除法都是一件运算速度很慢的指令在计算机中实现除法是比较复杂的。所以要减少除法运算的次数下面介绍一些简单方法来提高效率 1、通过数学的方法把除法变为乘法运算如if(a b/c),如果a、b、c都是正数则可写成if(a*c b) 2、让编译器有优化的余地如里你要做的运算是int型的n/8的话写成unsigned)n/8有利于编译器的优化。而要让编译器有优化的余地则除数必须为常数而这也可以用const修饰一个变量来达到目的。 九、将小粒度函数声明为内联函数inline 正如我们所知调用函数是需要保护现场为局部变量分配内存函数结束后还要恢复现场等开销而内联函数则是把它的代码直接写到调用函数处所以不需要这些开销但会使程序的源代码长度变大。 所以若是小粒度的函数如下面的Max函数由于不需要调用普通函数的开销所以可以提高程序的效率。 int Max(int a, int b) {return ab?a:b; }十、多用直接初始化 与直接初始化对应的是复制初始化什么是直接初始化什么又是复制初始化举个简单的例子 ClassTest ct1; ClassTest ct2(ct1); //直接初始化 ClassTest ct3 ct1; //复制初始化那么直接初始化与复制初始化又有什么不同呢直接初始化是直接以一个对象来构造另一个对象如用ct1来构造ct2复制初始化是先构造一个对象再把另一个对象值复制给这个对象如先构造一个对象ct3再把ct1中的成员变量的值复制给ct3从这里可以看出直接初始化的效率更高一点而且使用直接初始化还是一个好处就是对于不能进行复制操作的对象如流对象是不能使用赋值初始化的只能进行直接初始化。可能我说得不太清楚那么下面就引用一下经典吧 以下是Primer是的原话 “当用于类类型对象时初始化的复制形式和直接形式有所不同直接初始化直接调用与实参匹配的构造函数复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象然后用复制构造函数将那个临时对象复制到正在创建的对象”还有一段这样说“通常直接初始化和复制初始化仅在低级别优化上存在差异然而对于不支持复制的类型或者使用非explicit构造函数的时候它们有本质区别 ifstream file1(filename)://ok:direct initialization ifstream file2 filename;//error:copy constructor is private ” 注如还对直接初始化和复制初始化有疑问可以参考一下前面的一篇文章 C直接初始化与复制初始化的区别深入解析里面有有关直接初始化和复制初始化的详细解释。 补充 这里只是一点点的建议虽然说了这么多但是还是要说一下的就是要避免不必要的优化避免不成熟的优化不成熟的优化的是错误的来源因为编译器会为你做很多你所不知道的优化。 希望本文所述对提高大家C程序设计效率能有所帮助。
http://www.zqtcl.cn/news/183495/

相关文章:

  • 网站制作超链接怎么做厦门公司建站
  • 阿里云做的网站怎么备份建筑设计网站issuu
  • 网上做设计网站广西做网站找谁
  • 网站优化成本建设项目网站备案申请表
  • 做公众号首图网站上海短期网站建设培训
  • 网站开发最好佛山优化网站排名
  • 服务器搭建网站打不开网站建设信息平台
  • 宽屏蓝色企业网站源码如何编辑网站标题
  • 免费搭建手机网站广告公司怎么取名
  • 网站抓取超时错误c 高性能网站开发
  • 营销导向企业网站策划wordpress 不显示菜单
  • 特效视频网站用.net做视频网站的案例
  • 网站建设实用的网站视屏网站的审核是怎么做的
  • 网站模板之家免费下载福州网红餐厅
  • 西安网站设计与建设第三方检测机构
  • 手机网站推广法建设网站明细报价表
  • 一级a做爰片免费网站录像好商网的网站可以做中英文切换吗
  • 视频网站闪图怎么做网件路由器管理地址
  • 一个完整的网站建设网站模板去哪要
  • 烤漆 东莞网站建设水果香精东莞网站建设技术支持
  • 国家重大项目建设库网站北京网站开发外包公司
  • 建设免费网站制作二维码的软件app
  • 网站突然没收录了网站建设和运营的成本是多少钱
  • 家政公司网站模板wordpress防cc代码
  • 福田附近做网站公司网站反向链接
  • 南阳网站关键词哪做网站便宜
  • 往网站上做新东西需要什么智库网站建设
  • 网站建站系统程序做网站代理商好赚吗
  • 哪些网站是做食品dedecms转wordpress
  • 广东华迪工程建设监理公司网站网站的优化从哪里进行