Effective C++笔记(1)

(一)前言

Effective C++是Scott Meyers编著,由侯捷老师翻译,也是STL源码剖析的作者。假期刚考完驾照,在家不能荒废学习,开始看看这本C++经典,并做一些笔记。

本书标题提到“改善程序与设计的55个具体做法”,对应书中的目录,可以看到分为9大章节,55个条款。几乎涵盖了C++的所有内容:面向对象,资源管理,模板,内存管理等等。

接下来将分条款学习记录。


(二)视C++为一个语言联邦

美帝作为联邦国家,他的50州都有自己的立法和行政机关,这里提到C++为一个语言联邦,是因为C++作为一个多重泛型编程语言,支持面向对象、泛型等特性。就像联邦政府一样,C++主要有4个次语言,当使用不同的次语言时,某些守则可能改变:

1.C
2.Object-Oriented C++
3.Template C++
4.STL

文中提到的守则,我认为还是从效率层面来讲的。
比如书中的例子:

参数传递中两种方式:值传递和引用传递。当C-风格内置类型参数传递时值传递效率更高,而这个准则到了面向对象的类操作时,由于构造函数和析构函数的存在,引用传递往往更好。

C++高效编程守则视状况而变化,取决于使用C++的哪一部分。


(三)编译器替换预处理器

3.1const代替#define

也就是要减少#define的使用。
原因有二:

1.使用预处理器所用的符号名称可能将未进入记号表,当#define在其他文件时,一旦程序出错,错误信息将难以定位。
2.预处理器可能将宏定义盲目的替换,这也是显而易见的,在我们最早学习C/C++宏定义的时候就知道的简单道理。

取而代之的是用const来代替宏,例如:

#define pi 3.14//替换为
const double pi = 3.14;

使用const替换宏还有两个特殊情况:
一是:

const char * const authorName="Scott Meyers";

要使用两个const限定,表示指向常量的常量指针,语义上来说是没有问题的。

二是:
class专属的常量,用static修饰,例如:

class GamePlayer{
    private:
        static const int NumTurns=5;
        int scores[NumTurns];
};

带有类内初始值设定项的成员必须是常量也就是const限定字的作用,而static则限定了该常量只有一份实体。这里也侧面反映除了#define的一个小缺陷,因为仅仅是宏名称的替换,因此不能定义class专属的常量,也不能提供封装,即没有所谓的private #define这种东西。

3.2 enum hack的使用

主要是针对一些编译器不支持类内初始化设定,这样,我们的类内专属变量就必须在内外定义:

class GamePlayer{
    private:
        static const int NumTurns;
        int scores[NumTurns];
};
const int GamePlayer::NumTurns=5;

但是编译器又必须在编译期就知道数组的大小。
这样就会很尴尬,因为这个时候数组scores的大小就变得未知。
enum hack就可以解决这个问题,也是因为我们所需要的常量是个整型,而枚举类型是完全可以当做整型来用的。所以,修改上述代码:

class GamePlayer{
    private:
        enum {NumTurns = 5};
        int scores[NumTurns];
};

关于使用enum hack的三点需要知道的内容:

1.enum hack的地址不合法,这一点类似于#define,这就约束了指针和引用的使用。
2.enum hack是模板元变成的基础技术。
3.enum hack不会导致非必要的内存分配。

3.3 宏函数的陷阱

书中的例子,特意试了一蛤:

#define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b))
int f(int a)
{
    return a;
}

int main(int argc, char**argv)
{
    int a = 5;
    int b = 0;
    int res = CALL_WITH_MAX(++a, b);//最终a为7
    //int res=CALL_WITH_MAX(++a,b+10);//最终a为6
    cout << "res=" << res << endl;
    cout << "a=" << a << endl;
    system("pause");
    return 0;
}

遇到这种情况就很尴尬了,CALL_WITH_MAX的初衷是想把较大的参数作为函数f的实参,却造成了不同情况的不同效果。原因书中没有说明,但仔细一想,由于宏只是字符串的简单替换,上述例子中:

a>b时,++a会被执行两次(比较一次,比较结果为真时还要执行一次);
而反之a<b的话,++a只会在比较时执行一次,因为此时比较结果为假了。

我们使用预处理器实现的宏让它看起来像函数,不会招致函数调用带来的额外开销,但也会出现上述的问题,幸运的是,我们可以用template inline的方式解决,这都是书中后面将介绍的内容了。


(四)参考

1. Effective C++
2. C++的enum hack

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值