这本书只有短短100页,可是却可以称得上是脍炙人口。一年前初读此书时就感觉受益良多,而今再次重读,仍然不肯停顿一口气读完。针对书中指出的一些编程规则和建议,摘录下个人认为比较好的部分。

第1章 文件结构

为了 防止头文件被重复引用 ,应当用ifndef/define/endif结构产生预处理块。
用 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。
用 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。

第2章 程序的版式

一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。
if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{}。这样可以防止书写失误。
尽可能在定义变量的同时初始化该变量(就近原则)。
长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。

第3章 命名规则

标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
例如Windows应用程序的标识符通常采用“大小写”混排的方式,如AddChild。而Unix应用程序的标识符通常采用“小写加下划线”的方式,如add_child。别把这两类风格混在一起用。
变量的名字应当使用“名词”或者“形容词+名词”。

第4章 表达式和基本语句

不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。
假设布尔变量名字为flag,它与零值比较的标准if语句如下:

if (flag)    // 表示flag为真
if (!flag)    // 表示flag为假

应当将整型变量用“==”或“!=”直接与0比较。
假设整型变量的名字为value,它与零值比较的标准if语句如下:

if (value == 0)
if (value != 0)

不可模仿布尔变量的风格而写成

if (value)    // 会让人误解 value是布尔变量
if (!value)

不可将浮点变量用“==”或“!=”与任何数字比较。
应当将指针变量用“==”或“!=”与NULL比较。
指针变量的零值是“空”(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下:

        if (p == NULL)    // p与NULL显式比较,强调p是指针变量if (p != NULL)

每个case语句的结尾不要忘了加break,否则将导致多个分支重叠(除非有意使多个分支重叠)。
不要忘记最后那个default分支。即使程序真的不需要default处理,也应该保留语句    default : break; 这样做并非多此一举,而是为了防止别人误以为你忘了default处理。

第5章 常量

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

第6章 函数设计

const数据成员的初始化只能在类构造函数的初始化表中进行,例如

    class A{…A(int size);      // 构造函数const int SIZE ;};A::A(int size) : SIZE(size)    // 构造函数的初始化表{…}A  a(100); // 对象 a 的SIZE值为100A  b(200); // 对象 b 的SIZE值为200

如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。
return语句不可返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。例如

    char * Func(void){char str[] = “hello world”;    // str的内存位于栈上…return str;     // 将导致错误}

第7章 内存管理

用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。
不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
动态内存的申请与释放必须配对,防止 内存泄漏 。
用free或delete释放了内存之后,立即将指针设置为NULL,防止产生 “野指针” 。
注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
malloc返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的指针类型。
用malloc申请一块长度为length的整数类型的内存,程序如下:

        int  *p = (int *) malloc(sizeof(int) * length);

第8章 C++函数的高级特性

成员函数被 重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
参数缺省值只能出现在函数的声明中,而不能出现在定义体中。
关键字inline必须与函数定义体放在一起才能使函数成为内联,仅将inline放在函数声明前面不起任何作用。

第9章 类的构造函数、析构函数与赋值函数

    A(void);                    // 缺省的无参数构造函数A(const A &a);                // 缺省的拷贝构造函数~A(void);                    // 缺省的析构函数A & operate =(const A &a);    // 缺省的赋值函数

如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数。
例如

    class A{…A(int x);        // A的构造函数
}; class B : public A{…B(int x, int y);// B的构造函数};B::B(int x, int y): A(x)             // 在初始化表里调用A的构造函数{…
}  

类的const常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始化。
偷懒的办法处理拷贝构造函数与赋值函数
       偷懒的办法是:只需将拷贝构造函数和赋值函数声明为私有函数,不用编写代码。

例如:class A{ …private:A(const A &a);                // 私有的拷贝构造函数A & operate =(const A &a);    // 私有的赋值函数};

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

第10章 类的继承与组合

若在逻辑上B是A的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。

第11章 其它编程经验

如果输入参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针,起到保护作用。
当心那些视觉上不易分辨的操作符发生书写错误。我们经常会把“==”误写成“=”,象“||”、“&&”、“<=”、“>=”这类符号也很容易发生“丢1”失误。然而编译器却不一定能自动指出这类错误。
变量(指针、数组)被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。
当心变量的初值、缺省值错误,或者精度不够。
当心数据类型转换发生错误。尽量使用显式的数据类型转换(让人们知道发生了什么事),避免让编译器轻悄悄地进行隐式的数据类型转换。
当心变量发生上溢或下溢,数组的下标越界。
当心忘记编写错误处理程序,当心错误处理程序本身有误。
当心文件I/O有错误。
避免编写技巧性很高代码。
不要设计面面俱到、非常灵活的数据结构。
如果原有的代码质量比较好,尽量复用它。但是不要修补很差劲的代码,应当重新编写。
尽量使用标准库函数,不要“发明”已经存在的库函数。
尽量不要使用与具体硬件或软件环境关系密切的变量。
把编译器的选择项设置为最严格状态。

如果可能的话,使用PC-Lint、LogiScope等工具进行代码审查。

转载请注明出处!http://blog.csdn.net/lsh_2013/article/details/44651603

《高质量C/C++编程指南》学习笔记相关推荐

  1. 第二行代码学习笔记——第六章:数据储存全方案——详解持久化技术

    本章要点 任何一个应用程序,总是不停的和数据打交道. 瞬时数据:指储存在内存当中,有可能因为程序关闭或其他原因导致内存被回收而丢失的数据. 数据持久化技术,为了解决关键性数据的丢失. 6.1 持久化技 ...

  2. 第一行代码学习笔记第二章——探究活动

    知识点目录 2.1 活动是什么 2.2 活动的基本用法 2.2.1 手动创建活动 2.2.2 创建和加载布局 2.2.3 在AndroidManifest文件中注册 2.2.4 在活动中使用Toast ...

  3. 第一行代码学习笔记第八章——运用手机多媒体

    知识点目录 8.1 将程序运行到手机上 8.2 使用通知 * 8.2.1 通知的基本使用 * 8.2.2 通知的进阶技巧 * 8.2.3 通知的高级功能 8.3 调用摄像头和相册 * 8.3.1 调用 ...

  4. 第一行代码学习笔记第六章——详解持久化技术

    知识点目录 6.1 持久化技术简介 6.2 文件存储 * 6.2.1 将数据存储到文件中 * 6.2.2 从文件中读取数据 6.3 SharedPreferences存储 * 6.3.1 将数据存储到 ...

  5. 第一行代码学习笔记第三章——UI开发的点点滴滴

    知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...

  6. 第一行代码学习笔记第十章——探究服务

    知识点目录 10.1 服务是什么 10.2 Android多线程编程 * 10.2.1 线程的基本用法 * 10.2.2 在子线程中更新UI * 10.2.3 解析异步消息处理机制 * 10.2.4 ...

  7. 第一行代码学习笔记第七章——探究内容提供器

    知识点目录 7.1 内容提供器简介 7.2 运行权限 * 7.2.1 Android权限机制详解 * 7.2.2 在程序运行时申请权限 7.3 访问其他程序中的数据 * 7.3.1 ContentRe ...

  8. 第一行代码学习笔记第五章——详解广播机制

    知识点目录 5.1 广播机制 5.2 接收系统广播 * 5.2.1 动态注册监听网络变化 * 5.2.2 静态注册实现开机广播 5.3 发送自定义广播 * 5.3.1 发送标准广播 * 5.3.2 发 ...

  9. 第一行代码学习笔记第九章——使用网络技术

    知识点目录 9.1 WebView的用法 9.2 使用HTTP协议访问网络 * 9.2.1 使用HttpURLConnection * 9.2.2 使用OkHttp 9.3 解析XML格式数据 * 9 ...

  10. 安卓教程----第一行代码学习笔记

    安卓概述 系统架构 Linux内核层,还包括各种底层驱动,如相机驱动.电源驱动等 系统运行库层,包含一些c/c++的库,如浏览器内核webkit.SQLlite.3D绘图openGL.用于java运行 ...

最新文章

  1. linux ssh scp 使用跳板机 访问 远程服务器
  2. 你知道什么是AVL树吗?
  3. Python学习笔记:IO编程StringIO和BytesIO
  4. Primefaces,Spring 4 with JPA(Hibernate 4 / EclipseLink)示例教程
  5. linux用户怎么归纳到组,Linux用户和组命令总结
  6. C# 托管资源与非托管资源
  7. 217 - leetcode -存在重复元素 -数据结构类 先排序再操作
  8. 改善CSS的10种最佳做法,帮助你从样式中获得最大的收益
  9. 速成pytorch学习——7天模型层layers
  10. 完整的安全方案需要参考的几个方面
  11. VBA连接MySQL数据库以及ODBC的配置(ODBC版本和MySQL版本如果不匹配会出现驱动和应用程序的错误)...
  12. 安装LaTeX中文字体 xGBKFonts
  13. 浅谈“知识库管理系统”
  14. C语言全局变量和数组的应用
  15. 非平衡电桥电阻计算_用非平衡电桥如何测量电阻_非平衡电桥测量电阻详解
  16. pta算法:计算天数
  17. Ubuntu 开机未登录用户前自动连接wifi
  18. r语言rank降序_常见排序分析方法及R语言实现
  19. Kyligence联合创始人兼CTO李扬:用智能数据云打造全链路数字化转型
  20. QT报错cannot find -lxxx(xxx为被调模型)和undefined reference to’_imp__ZN11/14xxx(xxx为自己定义)

热门文章

  1. 贺利坚老师汇编课程54笔记:标志寄存器
  2. JVM学习之GC参数设置
  3. SQL Server-已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行...
  4. [置顶] Android之Handler用法总结
  5. Gnuplot的简介与常用操作
  6. [转载] python数据类型转换
  7. [转载] python numpy 总结
  8. .net core 部署应用程序注意事项
  9. 【Linux】解决用vi修改文件,保存文件时,提示“readonly option is set”
  10. Fiddler抓包【3】_设置断点修改