《Effective C++》读书笔记

来源:互联网 发布:app数据统计模板 编辑:程序博客网 时间:2024/05/01 11:01

第一章 从C转向C++

 

条款1:尽量用const和inline而不用#define

尽量用编译器而不用预处理

常量定义一般是放在头文件中(许多源文件会包含它),不会出现重定义错误.如果是非常量的话,就会出现重定义错误。

例1:

const double ASPECT_RATIO = 1.653;

const char * constauthorName = "Scott Meyers";

只有这样authorName才是常量。

 

例2:

class EngineeringConstants {// this goes in the class

private:      // header file

    static const double FUDGE_FACTOR;

 

};

// this goes in the classimplementation file

const doubleEngineeringConstants::FUDGE_FACTOR = 1.35;

 

但是,下面这样在VC6.0中不行,因为编译过程中编译器一定要知道数组的大小。可能在其他编译器可以。

class GamePlayer {

private:

    static const int NUM_TURNS;// constant eclaration

    int scores[NUM_TURNS];      // use of constant

 

};

const intGamePlayer::NUM_TURNS=10;   // mandatorydefinition;

       // goes in class impl.file

 

上面的问题可以通过枚举解决。

class GamePlayer {

private:

    enum { NUM_TURNS = 5 };  // "theenum hack" - makes

    // NUM_TURNS a symbolic name

    // for 5

    int scores[NUM_TURNS];// fine

};

 

顺便说一句,在你打算用模板写象max这样有用的通用函数时,先检查一下标准库(见条款49),看看他们是不是已经存在。

 

条款2:尽量用<iostream>而不用<stdio.h>

因为类型安全和扩展性是C++的基石

另外,scanf/printf系列函数把要读写的变量和控制读写格式的信息分开来

 

第一,有些iostream的操作实现起来比相应的C stream效率要低。第二,在标准化的过程中,iostream库在底层做了很多修改(参见条款49),所以对那些要求最大可移植性的应用程序来说,会发现不同的厂商遵循标准的程度也不同。第三,iostream库的类有构造函数而<stdio.h>里的函数没有,在某些涉及到静态对象初始化顺序的时候,如果可以确认不会带来隐患,用标准C库会更简单实用。

 

iostream库的类和函数所提供的类型安全和可扩展性的价值远远超过你当初的想象,所以不要仅仅因为你用惯了<stdio.h>而舍弃它。毕竟,转换到iostream后,你也不会忘掉<stdio.h>。

 

趋向<iostream>而不是<iostream.h>

 

条款3:尽量用new和delete而不用malloc和free

malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。

 

假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:

string *stringarray1=static_cast<string*>(malloc(10 * sizeof(string)));

string *stringarray2 = newstring[10];

 

其结果是,stringarray1确实指向的是可以容纳10个string对象的足够空间,但内存里并没有创建这些对象。而且,如果你不从这种晦涩的语法怪圈(详见条款m4和m8的描述)里跳出来的话,你没有办法来初始化数组里的对象。换句话说,stringarray1其实一点用也没有。相反,stringarray2指向的是一个包含10个完全构造好的string对象的数组,每个对象可以在任何读取string的操作里安全使用。

 

条款4:尽量使用c++风格的注释

/* */容易出错! 例:

if ( a > b ) {

    /*  int temp = a; /* swap a and b */

       a= b;

       b= temp;

    */

}

 

值得指出的是,有些老的专门为c写的预处理程序不知道处理c++风格的注释,所以象下面这种情形时,事情就不会象预想的那样:

#define light_speedp 3e8 // m/sec (in a vacuum)

对于不熟悉c++的预处理程序来说,行尾的注释竟然成为了宏的一部分!当然,正象条款1所说的那样,你无论如何也不会用预处理来定义常量的。