您的位置:首页 > 编程语言 > C语言/C++

C++编程建议、原则和理念——性能

2013-12-26 17:32 197 查看
API性能:

(1)编译时速度

(2)运行时速度

(3)运行时内存开销

(4)库的大小

(5)启动时间

1.应该通过const引用而非传值方式传递不会改变的对象。这样可以避免创建和销毁对象的临时副本,及副本中所有的成员和继承对象的内存与性能开销。

2.最小化#include依赖:一般来说,只有在自己的类中将某个类的对象作为数据成员使用时,或者需要继承某个类时,才应该包含那个类的头文件。

仅仅前置声明你自己API中的符号。头文件应该#include或者前置声明其所有的依赖项。

注意:只前置声明你自己的代码才是安全的做法。使用前置声明,意味着你非常清楚符号在被省略的头文件中怎样声明。例如,如果你前置声明了一个外部头文件,并且该头文件具有不同的版本,那么如果该头文件中的类声明改为typedef,或者类被修改为模板类时,就会破坏前置声明。这就是不应该前置STL对象的原因之一了。

3.冗余的#include警戒语句:考虑在头文件中加入冗余的#include警戒语句,为客户优化编译时间

降低过多包含文件解析开销的另一种方法是,在包含点增加冗余预处理警戒语句。例如:对于一个名为example.h的包含文件

#ifndef EXAMPLE_H
#define  EXAMPLE_H

//大量代码

#endif
你可以在另一个头文件中以如下方式包含该文件:
#ifndef  EXAMPLE_H
#include example.h
#endif
4.声明常量:应使用extern声明全局作用域的常量,或者在类中以静态const方式声明常量,然后在.cpp文件中定义常量值。这样就减少了包含这些头文件的模块的目标文件大小。更可取的方法是将这些常量隐藏在函数调用背后。

5.使用构造函数初始化列表,从而每个数据成员减少一次调用构造函数的开销。这些应该在.cpp文件中声明,以便隐藏实现细节。

注意:(1)初始化列表中的变量顺序必须与类中指定的顺序一致。(2)不能再初始化列表中指定数组,但是可以指定std::vector。无论如何,应该优先选择std::vector而非数据结构。(3)如果声明的是派生类,那么每个基类的默认构造函数都会被隐式调用。此外,也可以使用初始化列表调用非默认构造函数。如果指定了非默认构造函数,必须在调用任何成员变量之前调用基类构造函数。(4)如果把成员变量声明为引用或者const,那么就必须通过初始化列表来初始化它们,从而避免由构造函数定义其恒定不变的唯一初值。

6.内存优化:对象越小,就越适合缓存。

几种缩小对象大小的方法:(1)根据类型聚集成员变量。现代计算机一次访问内存中的单个“字”长。因此C++编译器会对齐某些数据成员,使得它们的内存地址落在字长边界。(2)使用位域。位域是成员变量的修饰符,它指定变量应该占有多少位,例如,int tinyInt:4.(3)使用联合。联合是数据成员共享内存空间的一种结构。(4)除非必要,不要添加虚方法。一旦给类添加虚方法,类就需要维护一个虚表。每种类型虽然只需要分配一份虚表副本,但是指向虚表的指针在每份对象实例中都会被存储。这给对象的总体大小增加了一个指针的开销。(5)使用大小明确的类型。也就是说能用float表示的绝不用double,能用short表示的绝不用int。

根据成员变量类型对它们加以类聚,从而优化对象大小。

考虑使用位域进一步压缩对象,但是要注意它对性能的影响。

使用大小明确的类型指定变量所需的最大位数。

(根据AMD软件优化指南的建议,类型从大到小排序:int、char、bool)

7.避免在公有头文件中使用内联代码,除非能证明代码会导致性能问题,并确认内联可以解决该问题。内联通常适用于短小、简单、频繁调用的函数。

8.写时复制:节省内存最好的办法之一是确实需要时再分配。这是写时复制技巧的本质目标。

9.迭代元素

迭代器应尽量使用前置自增操作符(++it),而非后置自增操作符。以避免临时对象的构造和析构。

支持随机访问的STL容器类提供了两种访问方式。[]操作符,通常不做边界检查,所以可以高效的实现。 at()方法检查所提供的索引是否越界,如果越界则抛出异常。因此,这种做法会比[]操作符慢。

采用迭代器模型遍历简单的线性数据结构。对于链表或树形数据结构,如果迭代性能很重要,那么就应该考虑使用数组引用。

10.性能分析

时效性分析

内存开销分析

多线程分析




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: