Effective C++学习笔记(1)

不知道是本人水平太差还是什么原因,总感觉侯捷的翻译非常别扭难理解。实在看不下去的话得找英文版了,虽然已经花钱在中文版上面了。



Term01: View C++ as a federation of languages.

这条大概就是说C++里有四块比较独立的内容:

  1.  面向过程的C(熟悉)
  2.  面向对象的类(熟悉)
  3.  实现泛型特性的模版(了解)
  4.  标准模板库STL(了解)

总结起来,C++是一个集合了太多特性的语言。这些不同的特性很多都是完全迥异的思维模式,所以也导致了C++是一个较为复杂难以掌握的语言。学好这些特性,关是理解每个特性针对什么样的需求,更好的有的放矢。




Term02:Prefer consts, enums, and inlines to #defines.

#define是预处理指令,而其他几项为编译器处理的内容。#define的劣势在于:

1. #define定义的对象并非符号,而是预处理阶段的文本占位符,因此这个对象不会存在于编译器生成的符号表中,导致的结果就是在编译阶段或运行调试阶段出现错误,将不会报告到这个定义的对象这里,而是替换后的表达式。例如 #define pi 3.14,如果pi的用法有误,则会报3.14有误,这样会使问题的定位变得困难。而使用const定义的常量会进入符号表,就不存在这个问题。

2. 接1的话题。由于#define的对象不是符号,在所有用到这个对象的地方,都将有一份3.14的代码拷贝,从而使得代码区的占用空间大大增加,而使用const等定义的对象则只会在每个调用它的地方保存一个链接。

3. #define没有作用域,缺乏封装性,自定义之后就都可以用,const常量可以定义为类私有成员,限定访问范围。

4.用#define定义的表达式,由于其本质并非函数,因此在文本替换时会有很多意外的情况发生。表达式中的所有参数都需要使用括号,否则会遭遇运算符的优先级问题,从而破坏表达式的逻辑功能。例如:

#define SUM(a,b) a+b
result = SUM(x,y)*2
结果不是(a+b)*2,二是a+b*2。另外一个例子就是对于多个表达式的define,需要使用do{}while(0)。如下:

#define FUNC(a,b) a+=b;\
a*=b
if(0) FUNC(x,y);
这里结果不是:

if(0) {
	a+=b;
	a*=b;
}
而是

if(0)
	a+=b;
a*=b;
也就是说a*=b;并没有按照预想的并入if(0)性。而这个问题,并不能靠大括号来解决,例如:

#define FUNC(a,b) {a+=b;a*=b;}
if(0) FUNC(a,b);
else return;
这里展开后为:

if(0) {a+=b;a*=b;};
else return;
多余的一个分号编译不过。

本来使用#define的目的是为了减少函数调用的开销从而优化性能,结果换来的是编写#define表达式时的麻烦。而C++的inline函数完美的解决了这个问题。上面的这些写法的问题都不再存在,同时保持了跟使用#define一样性能(除了inline被否决的情况)。

#define还有一个问题,即使实施了所有的封装手段,其表达结果依然不能完全等同于函数的效果,例如page16页对三目运算符的定义。因为函数的参数传递方式是拷贝压栈,运行过程不会改变调用栈现场的原参数,而#define非拷贝参数,二是直接用的原来的变量,调用的过程损坏了原来的现场。

5. #define由于是预处理而非编译,不存在类型检查。这样好处是可以适用任何参数类型,不好处就是没有类型检查安全性下降。而inline本身是对参数进行类型检查的,确保表达式的使用没有错误。另一方面,inline函数也可以做成类型无关的,使用模版就OK了。

在这个条款中提到了两个关于const特殊用法。一是常量指针,多数用在头文件内(?),此外尽量用std::string替代char*或char[]。二是class的成员常量,需要定义为static的,而且需要在类实现的部分初始化。不过某些最新的编译器支持在声明的时候就初始化。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值