effective C++读书笔记(一)

本文深入探讨了C++编程中高效编程的关键准则,包括如何将C++视为一个语言联邦,合理使用const、enum和inline替代#define,以及如何在使用const、初始化对象和选择关键词时提高代码质量。此外,文章还强调了使用const的重要性,提供了关于构造函数、静态成员函数和初始化顺序的详细指导,旨在帮助开发者编写更高效、更易于维护的C++代码。

1. 让自己习惯C++(Accustoming yourselfto C++)

条款01: C++ 为一个语言联邦(ViewC++ as a federation of languages)

C++已经不是单一的语言,而是一个由相关语言组成的联邦。它由若干次语言组成,分别为:

1 C。区块(blocks) 、语句(statements) 、预处理器(preprocessor) 、内置数据类型(built-in datatypes) 、数组(arrays) 、指针(pointers) 等统统来自C

2Object-OrientedC++。这部分是C with Classes : classes (包括构造函数和析构函数) ,封装(encapsulation) 、继承(inheritance) 、多态(polymorphism) virtual 函数(动态绑定) ……

3Template C++。这是C++ 的泛型编程(genericprogramming) 部分,也是大多数程序员经验最少的部分。就是所有的东西都是模板,与具体的类型没有关系

4STL STL 是个template 程序库,包括容器(containers) 、迭代器(iterators) 、算法(algorithms) 以及函数对象(functionobjects)

所以,要想让C++高效,首先我们必须弄清楚我们现在是处在上面4种的哪一个语言层次,每一个语言层次我们关注点是不同,高效编程的规则也不一样,例如,对于内置类型:pass by value比较好,对于用户自定义,用pass by reference to const比较好,对于STL,还是得用pass by value 。所以,想编牛逼的程序,先弄清楚自己在用C++的什么层次

条款02: 尽量以const,enum, inline替换#define(Prefer consts,enums,and inlines to #define)

本条款讨论了C语言中的#defineC++程序设计中的带来的问题并给出了替代方案。

C语言中的宏定义#define只是进行简单的替换,对于程序调试,效率来说,会带来麻烦。在C++中,对于单纯变量,最好用constenums对象代替#define;对于形似函数的宏(macros),最好用inline代替#define

    编译过程:.c文件--预处理-->.i文件--编译->.o文件--链接-->bin文件

预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。可见预处理过程先于编译器对源代码进行处理。预处理指令是以#号开头的代码行。

#defineASPECT_RATIO 1.653 这个不好,为什么呢?记号名称ASPECT_RATIO不能被编译器看见,不方便debug,盲目宏替换导致目标代码出现多份,没有类型检查,替代方法:const floatASPECT_RATIO = 1.653

#define不能搞出类的专属常量,但是const+static可以

classGamePlayer{

private :

     static const int NumTurns = 5  ; //声名式,并非定义式

}

如果非要一个定义式,则在实现文件,非头文件中写:const int GamePlayer::NumTurns = 5

如果,类的某个成员还依赖NumTurns , 那么,就用class里的enum

classGamePlayer{

private :

   enum( NumTurns = 5) ;

   int score[NumTurns] ;

}

常量替换#define两点注意:

·        定义常量指针:

     const char*authorName = “Shenzi”;
       cosnt std::string authorName("Shenzi");

·        类专属常量:

     static const int NumTurns= 5;//static 静态常量 所有的对象只有一份拷贝。
    
万一你编译器不允许“static整数型class常量完成“in calss初值设定(即在类的声明中设定静态整形的初值),我们可以通过枚举类型予以补偿:
      
enum { NumTurns = 5 };
    *
取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法。如果你不想让别人获取一个pointerreference指向你的某个整数常量,enum可以帮助你实现这个约束。

 

宏可以搞小函数,但是麻烦的YB,记得加各种括号,还要想到各种安全性的东西,替代方法就是用inline

当然,预处理器还是有用的,#include, #ifndef 之类还是很有用的,预处理器包括宏定义,文件包含,条件编译

关注ifndefexternword,学习了extern关键字(加C或者加变量两种情况)。

 

条款03: 尽可能使用const(Useconst whenever possible)

本条款总结了const的使用场景和使用它带来的好处。

const就是加上一个约束,不能改变

1、关键字在星号左边,表示被指物事常量 const char *pcharconst *p两种写法意义一样,都说明所致对象为常量;

2、关键字在星号右边,表示指针自身是常量

3constvector<int>::iterator iter 表示iter自身是常量,不能瞎指

4vector<int>::const_iteratoriter 表示iter所指对象是常量,不能通过iter改变

 

上面只是一般的东西,const最狠的地方是函数的声明(参数,返回值,函数自身)

参数和返回值都比较好理解,关键是函数自身

 1、关键点:两个成员函数如果只是常量性不同,可以实现重载改善C++要用pass byreference to const,如果有相应的const函数多好。

2const函数,只能操作类的const成员,但是。如果给变量加上mutable关键字,那么,const成员函数也能对private成员变量赋值修改。

3应当运用const成员函数实现出其non-const的孪生兄弟版本,不能反过来。即non-const版本调用const版本可避免代码重复。移除const的动作const_cast,加上const的动作static_cast,见条款27

 

条款04: 确定对象被使用前已先被初始化(Makesure that objects are initialized before they’re used)

本条款告诫程序员,在C++程序设计中,在使用对象之前,应该对其初始化,以避免不必要的错误。同时,给出了高效初始化对象的方法和正确初始化对象的方法。内置对象,显示初始化,类对象,通过构造函数初始化。

1构造函数最好使用成员初值列(member initialization list) ,而不要在构造函数本体内使用赋值操作(assignment) 类对象的初始化,在进入类的构造函数之前就已经完成了,所以,如果在构造函数中用赋值,相当于1default ctor + 1copy assignment , 如果直接用初始化列表,那么就是1copy ctor 或者 1default ctor 显然后者效率更高。初值列列出的成员变量,其排列次序应该和它们在class 中的声明次序相同。

构造函数的运行顺序是先祖先,后儿子,析构相反自己中按照类中变量的声明顺序初始化,而不是初始化列表中的顺序

2C++定义于不同编译单元内的non-local static对象的初始化次序无明确定义所以最好以local static对象替换non-local static对象,具体如下所示。这也是设计模式中Singleton模式的一种常见实现手法。

class FileSystem { ... };
FileSystem&  tfs()      //用这个函数来代替non-local static对象
{
 static  FileSystem  fs;     // 以localstatic的方式定义和初始化对象
 return fs;         // 返回一个引用,指向local static对象
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值