高质量C++编程指南-读书笔记

1、用 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索),用 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)

2、不提倡使用全局变量,尽量不要在头文件中出现象 extern int value 这类声明

3、尽可能在定义变量的同时初始化该变量(就近原则)

4、推荐将 public 类型的函数写在前面,而将 private 类型的数据写在后面,采用这种版式的程序员主张类的设计“以行为为中心”,重点关注的是类应该提供什么样的接口(或服务)

5、不可将浮点变量用“==”或“!=”与任何数字比较。千万要留意,无论是 float 还是 double 类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。

6、在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少 CPU 跨切循环层的次数

7、实事求是地说,错误是程序员自己造成的,不是 goto 的过错。goto 语句至少有一处可显神通,它能从多重循环体中咻地一下子跳到外面,用不着写很多次的 break 语句

8、C++ 语言可以用 const 来定义常量,也可以用 #define 来定义常量。但是前者比后者有更多优点:

        (1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。

        (2) 有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。

9、尽量在 C++ 程序中只使用 const 常量而不使用宏常量,即 const 常量完全取代宏常量。

10、在类中定义枚举变量,从而实现类中定义常量的功能。类中之所以不能用const修饰变量,并给变量赋值常量,那是因为每个类都有自己的实体,理论上每个const常量也是可以不同的,而且只有在类初始化的时候,这个常量才会被赋值。

11、如果输入参数以值传递的方式传递对象,则宜改用“const &”方式来传递,这样可以省去临时对象的构造和析构过程,从而提高效率。

12、尽量避免函数带有“记忆”功能。相同的输入应当产生相同的输出。

13、用 malloc 或 new 申请内存之后,应该立即检查指针值是否为 NULL。防止使用指针值为 NULL 的内存。

14、不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

15、用 free 或 delete 释放了内存之后,立即将指针设置为 NULL,防止产生“野指针”。

16、编译器总是要为函数的每个参数制作临时副本,指针参数 p 的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p 的内容,就导致参数 p 的内容作相应的修改。这就是指针可以用作输出参数的原因。

17、extern“C”的作用就是告诉 C++编译译器,函数 foo 是个 C 连接,应该到库中找名字_foo 而不是找_foo_int_int。C++编译器开发商已经对 C 标准库的头文件作了 extern“C”处理,所以我们可以用#include 直接引用这些头文件。

18、如果仅仅区别重载与覆盖并不算困难,但是 C++的隐藏规则使问题复杂性陡然增加。这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

        (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

        (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

19、如果函数有多个参数,参数只能从后向前挨个儿缺省,否则将导致函数调用语句怪模怪样, void Foo(int x=0, int y, int z=0); 如果执行Foo(2,3), 将不知道缺省的是x还是z。

20、对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱。

21、C++ 语言的函数内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作类的数据成员。所以在 C++ 程序中,应该用内联函数取代所有宏代码

22、关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用

23、定义在类声明之中的成员函数将自动地成为内联函数,

24、“缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方式来实现,倘若类中含有指针变量,这两个函数注定将出错。

25、构造函数有个特殊的初始化方式叫“初始化表达式表”(简称初始化表)。初始化表位于函数参数表之后,却在函数体 {} 之前。这说明该表里的初始化工作发生在函数体内的任何代码被执行之前。

26、类的 const 常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始化

27、构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程

28、一个有趣的现象是,成员对象初始化的次序完全不受它们在初始化表中次序的影响,只由成员对象在类中声明的次序决定。这是因为类的声明是唯一的,而类的构造函数可以有多个,因此会有多个不同次序的初始化表。如果成员对象按照初始化表的次序进行构造,这将导致析构函数无法得到唯一的逆序

29、如果我们实在不想编写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的缺省函数,怎么办? 偷懒的办法是:只需将拷贝构造函数和赋值函数声明为私有函数,不用编写代码

30、基类的构造函数、析构函数、赋值函数都不能被派生类继承。如果类之间存在继承关系,在编写上述基本函数时应注意以下事项

        (1) 派生类的构造函数应在其初始化表里调用基类的构造函数

        (2) 基类与派生类的析构函数应该为虚(即加 virtual 关键字),如果不为虚函数将有可能造成无法调用派生类的析构函数造成内存泄露

        (3) 在编写派生类的赋值函数时,注意不要忘记对基类的数据成员重新赋值

31、任何不会修改数据成员的函数都应该声明为 const 类型。如果在编写 const 成员函数时,不慎修改了数据成员,或者调用了其它非 const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值