Effective C++ 01

来源:互联网 发布:mac上安装jmeter 编辑:程序博客网 时间:2024/06/04 00:25

Rule one

视C++为一个语言联邦 (view C++ as a federation of languages)

 

理解C++必须认识其他四种次语言:C,object-oriented  C++,Template C++, STL

 

总结:

C++的高效编程守则视情况而比变化,取决于你使用C++的那个部分

 

Rule two

尽量用const,enum,inline替换#define (Prefer const enums and inlines to #defines)

 

使用编译器替换预处理器是最合理的。

 

#define ASPECT_RATIO 123

1.预处理的记号名称有可能没有进到记号表内,在编译出错的时候会造成困惑。错误信息内会提及123 但是不会提及ASPECT_RATIO.

2.预处理器会盲目的将ASPECT_RATIO替换成123, 当对于浮点常量而言会导致代码内出现多份数据。

 

解决方案: const int ASPECT_RATIO = 123;(用常量替换#define)

 

特殊情况:

1.定义常量指针, 因为常量指针一般都定义在头文件一边复用,所以有必要声明为const。

2.class专属常量,为确保此常量至多只有一份 必须成为一个static对象。

 

enum hack

旧式编译器不支持“in class 初值设定” 但是需要在初始化的时候用到则可以使用enum hack的方式

class Test

{

enum { nWord = 1  };// 符号常量的声明

int array[nWord];

}

 

enum hack的好处:

1.enmu hack的行为更像是#define 而不是const 无法获取该变量位置(该方法的作用是在于解决的#define无法控制在类中的作用域)

2.不会导致不必要的内存分配

 

总结:

1.对于单纯变量,最好用const和enums来替换#define

2.对于形似函数的宏, 最好改用inline函数替换#define

 

Rule three

尽可能的使用const (Use const whenever possible)

 

const制定了一个语言约束(该值无法被修改)并且编译器会强制执行这个约束。

 

const语法定义

const char*   对象常量

char *const   指针常量

constchart* const 对象和指针都是常量

 

const和*的位置关系决定,与类型位置无关

const char*

char const* 一致

 

函数返回一个const对象能够减少因客户导致的意外。

 

const 成员函数

const的成员函数主要用于操纵const对象

注意:

1.两个成员函数如果只是常量性不同,可以被重载。(C++一个很重要的特性)

2.函数的返回值都是值拷贝,所以可以赋值。

 

bitwise  constness:成员函数只有不更改对象的任何成员变量

logical  constness: 成员函数可以修改其处理对象内的bits,但是只有在客户端侦测不出的情况下才可以。

bitewise的问题在于一个更改了指针所指对象的成员函数虽然不是const但是不会引起编译器异议。

如果需要在常量长远函数内修改成功元变量可以使用mutable来修饰成员变量。

 

const 和 non-const成员函数中避免重复

利用转型(?) static进行安全转型 const进行const的添加和移除。

 

注意:const函数调用non const 函数是一种错误的行为,因为它可能会导致const对象被修改 但是编译器并没有发现。

 

总结:

1.const可以帮助编译器侦测错误用法,但是存在缺陷。可以用于对象 参数 返回类型 成员函数本体等。

2.编译器强制实施bitwise constness 但是编写时应当使用 概念上的常量性

3.当const和non-const成员函数有实质等价的实现时,廪nonconst版本调用const版本可避免代码重复。

Rule four

确定对象被使用前已先被初始化 (Use const whenever possible)

 

C++在不同平台和不同情况下对于未初始化的参数默认数据是不可预知的,最佳的处理方式是永远在使用之前对对象进行初始化。

 

对于构造函数而言 可以用初始化和赋值来处理参数,成员初值列来实现初始化。

初始化的效率较高,原因:赋值是先初始化在进行赋值,比初始化多出一布操作。

 

对于设置默认值的参数可以在初始化列表内进行无参初始化,这样保证所有的参数都在初始化列表内,防止出现有些参数没有初始化。而对于某些赋值和初始化表现一样良好的成员变量则可以单独写一个私有函数来做赋值,适用于某些初始值由文件或数据库读入的参数。

初始化列表注意:

最好以声明顺序进行排序, 原因如下:

 

C++是有固定的成员初始化次序:

1.基类比派生类更早初始化。

2.class 的成员变量总是以声明的顺序被初始化。

C++对于不同编译单元的静态对象(或者说no local static)初始化顺序没有明确的定义。

解决方案:将no local static搬到专属函数内。

 

总结:

1.class内置对象需要手工初始化,因为C++不保证初始化他们。

2.构造函数最好使用成员初始化列表而不是赋值操作,其在初始化列表内的顺序应当与其声明的顺序相同。

3.为避免跨编译单元的初始化次序问题,local static对象应当替换non local static对象。