容易成为性能瓶颈的C++语言特性

 
C++应用程序性能优化笔记(四)——构造函数性能
2010-05-18 20:39

容易成为性能瓶颈的C++语言特性

对程序的性能问题,根本原因并非采用什么语言编写程序。如果程序的框架设计不作修改,单纯地把一个C++程序用C或者汇编改写,也不能保证总体性能会有提高。因此,正确的思路应该是:首先检查和反思程序的总体框架,然后用性能检测工具对实际运行进行准确测量,找出关键路径和瓶颈所在,然后针对瓶颈进行分析和优化。

一些容易成为程序瓶颈的C++语言特性或操作如下:

缺页。缺页往往意味着需要外部存储,因此需要尽量避免

从堆中动态申请和释放内存。要尽可能优先考虑从线程栈中获得内存,因为堆比栈慢许多,而且堆一般不可能都在物理内存中,从堆中生成的对象,指针在栈上,本身却在堆中,即使相邻生成的两个对象,内存位置上也可能相隔很远。因此用指针引用这些对象时,很可能会造成缺页。而当前栈帧空间所在内存页肯定在物理内存中,对栈中的变量存取则不会引起缺页。

复杂对象的创建和销毁。对象创建只需要一条语句,却可能是一个深层次的递归调用。另外,临时对象也是要高度警惕的。

函数调用。函数调用有固定的额外开销,调用频繁时,容易造成不必要的开销。宏和内联函数都是为了消除这些固定额外开销。提倡使用内联函数,宏不便开发者进行开发和调试。

构造函数和析构函数性能分析

创建一个对象,首先需取得所需的内存,然后在该内存上执行构造函数。

创建对象时,如果从线程运行栈中创建(局部对象,语句类似Object obj;),则在程序进入其作用域时,该对象的内存已经分配好了(一般都是通过移动栈指针),Object obj;一句只需调用构造函数,且这种创建方式不需要程序显式地调用析构函数,在程序运行到该对象作用域的终点时会自动调用析构函数,将空间返回给线程栈。

如果从全局堆中创建对象,即通过newmalloc创建,对象的指针是一个局部对象,需要从线程栈中分配,而对象本身的内存是从全局堆中分配的,需要显式调用deletefree来销毁。用deletefree来销毁对象时,会调用其析构函数,并将所占的全局堆内存空间返回。但从销毁对象到程序退出该作用域,对象的指针还存在于栈中,并指向对象本来的位置。显然,这种情况下调用指针是非常危险的。Win32平台下访问这种指针,结果有三种可能情况:访问违例、取得无意义值、取得其他对象。第一种会导致进程崩溃,后两种虽然不会立即崩溃,但是可能会有不可预测的行为操作或造成对象不必要的变化,需要谨慎避免。

构造函数构造对象时分两个步骤:初始化和执行构造函数的函数体。需要注意几点:

--构造函数是一个递归操作,即先父类后子类,父类还有父类就先构造最上面的父类。每一个在构造时都有严格的顺序,即按成员变量在类中的声明顺序进行初始化。故在初始化列表中成员的声明前后实际是无意义的。尽量养成使初始化列表与成员声明顺序一致的习惯,而且还要避免用某个成员变量的值初始化另外一个成员变量。

--千万不要以为只有初始化列表里列出来的成员变量才在执行构造函数体之前进行初始化的。事实上,即使没有在初始化列表中出现,所有成员变量仍然是在初始化这一步骤(也就是在执行构造函数的函数体前)完成初始化的。所以,我们常常在构造函数的函数体内对变量进行初始化,实际是非常浪费和降低效率的。应该养成用初始化列表进行赋初值的习惯。书中有个程序,就是通过多次循环来检验在构造函数的函数体内部进行初始化对性能的影响,在循环足够大的情况下,这种方法耗时是非常显著的。

--父类对象和一些成员变量没有出现在初始化列表中时,执行默认构造函数(也就是没有参数的那个构造函数)。如果没有定义构造函数,编译器会为其生成默认的构造函数。但是!!如果定义了其他类型的构造函数而没定义默认的构造函数,则会阻止编译器生成默认构造函数,就会编译出错。(我试过了,真的会提示error C2512: no appropriate default constructor available

--常量和引用型成员变量必须要在初始化列表中进行初始化。以前学C++也学过这点,但是知其然不知其所以然。现在明白了,因为这两类一旦被赋值,整个生命周期内都不能修改,而在执行构造函数的函数体前,所有成员变量已经被初始化了,所以不能在构造函数体内对其赋值。

--大型复杂系统中,如果需要生成的对象属于一个复杂继承体系的末端类,则其构造会引起一长串递归构造,会成为消耗CPU操作的主要部分。

避免临时变量

C/C++语言的函数调用都是“值传递”的,也就是说,在调用函数时,实际生成了一个参数的副本,在函数体内部所有修改都是针对这个副本的,因此这些修改在函数结束后会全部丢失。因此,最好使用引用传递参数(如果不需要修改,可传入常量引用参数),避免不必要的构造和析构操作降低效率。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
英特尔® C++编译器Cilk语言扩展 ............................................................................................... 1 1. 介绍............................................................................................................................................ 7 1.1 目标读者 ............................................................................................................................... 7 1.2 前提条件 ............................................................................................................................... 7 1.3 排字约定 ............................................................................................................................... 7 1.4 附加资源和信息 ................................................................................................................... 7 2. 新手上路 .................................................................................................................................... 8 2.1 编译运行一个Cilk用例 ..................................................................................................... 8 2.1.1 编译生成 qsort ........................................................................................................... 8 2.1.2 执行 qsort ................................................................................................................... 9 2.1.3 观察多核系统中的加速 ............................................................................................... 9 2.2 改写一个C++程序 .............................................................................................................. 10 2.2.1 从一个串行程序开始 ................................................................................................. 11 2.2.2 使用_Cilk_spawn加入并行性 .................................................................................. 12 2.2.3 编译,执行和测试 ..................................................................................................... 14 3. 编译、运行和调试Cilk程序 ......................................................

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值