![](https://img-blog.csdnimg.cn/20201014180756930.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
高质量编程指南
仓Rainy
这个作者很懒,什么都没留下…
展开
-
附录 A :C++/C 代码审查表
转载 2014-05-25 17:52:47 · 443 阅读 · 0 评论 -
4.5 for 语句的循环控制变量
【规则4-5-1】不可在for 循环体内修改循环变量,防止for 循环失去控制。【建议4-5-1】建议for 语句的循环控制变量的取值采用“半开半闭区间”写法。示例 4-5(a)中的x 值属于半开半闭区间“0 =循环次数为N。示例 4-5(b)中的x 值属于闭区间“0 =环次数为N。相比之下,示例4-5(a)的写法更加直观,尽管两者的功能是相同的。转载 2014-05-17 20:15:56 · 2929 阅读 · 0 评论 -
4.2 复合表达式
如 a = b = c = 0 这样的表达式称为复合表达式。允许复合表达式存在的理由是:(1)书写简洁;(2)可以提高编译效率。但要防止滥用复合表达式。转载 2014-05-17 20:23:23 · 557 阅读 · 0 评论 -
2.4 对齐
转载 2014-05-18 08:38:27 · 297 阅读 · 0 评论 -
8.1 函数重载的概念
8.1.1 重载的起源自然语言中,一个词可以有许多不同的含义,即该词被重载了。人们可以通过上下文来判断该词到底是哪种含义。“词的重载”可以使语言更加简练。例如“吃饭”的含义十分广泛,人们没有必要每次非得说清楚具体吃什么不可。别迂腐得象孔已己,说茴香豆的茴字有四种写法。在 C++程序中,可以将语义、功能相似的几个函数用同一个名字表示,即函数重载。这样便于记忆,提高了函数的易用性,转载 2014-05-18 16:26:45 · 393 阅读 · 0 评论 -
7.8 有了malloc/free 为什么还要new/delete ?
malloc 与free 是C++/C 语言的标准库函数,new/delete 是C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象在消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函转载 2014-05-18 10:39:28 · 300 阅读 · 0 评论 -
第 6 章函数设计索引
函数是C++/C 程序的基本功能单元,其重要性不言而喻。函数设计的细微缺点很容易导致该函数被错用,所以光使函数的功能正确是不够的。本章重点论述函数的接口设计和内部实现的一些规则。函数接口的两个要素是参数和返回值。C 语言中,函数的参数和返回值的传递方式有两种:值传递(pass by value)和指针传递(pass by pointer)。C++ 语言中多了引用传递(pass by转载 2014-05-18 09:00:24 · 328 阅读 · 0 评论 -
6.1 参数的规则
【规则6-1-1】参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void 填充。例如:void SetValue(int width, int height); // 良好的风格void SetValue(int, int); // 不良的风格float GetValue(void); // 良好的风格float GetValue()转载 2014-05-18 09:03:28 · 392 阅读 · 0 评论 -
const 有什么用途?(请至少说明两种)
答:(1)可以定义 const 常量(2)const 可以修饰函数的参数、返回值,甚至函数的定义体。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。转载 2014-05-17 14:35:00 · 5341 阅读 · 0 评论 -
1.4 头文件的作用
早期的编程语言如Basic、Fortran 没有头文件的概念,C++/C 语言的初学者虽然会用使用头文件,但常常不明其理。这里对头文件的作用略作解释:(1)通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。转载 2014-05-17 15:57:00 · 282 阅读 · 0 评论 -
2.2 代码行
1.【规则2-2-1】一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。2.【规则2-2-2】if、for、while、do 等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{}。这样可以防止书写失误。示例 2-2(a)为风格良好的代码行,示例2-2(b)为风格不良的代码行。转载 2014-05-17 16:11:49 · 303 阅读 · 0 评论 -
4.3 if 语句
if 语句是C++/C 语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if 语句。本节以“与零值比较”为例,展开讨论。4.3.1 布尔变量与零值比较【规则4-3-1】不可将布尔变量直接与TRUE、FALSE 或者1、0 进行比较。根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE 的值究竟是什么并没有统一的标准。例如转载 2014-05-17 20:21:44 · 305 阅读 · 0 评论 -
3.2 简单的Windows 应用程序命名规则
作者对“匈牙利”命名规则做了合理的简化,下述的命名规则简单易用,比较适合于Windows 应用软件的开发。转载 2014-05-17 20:31:11 · 399 阅读 · 0 评论 -
2.7 注释
C 语言的注释符为“/*…*/”。C++语言中,程序块的注释常采用“/*…*/”,行注释一般采用“//…”。注释通常用于:(1)版本、版权声明;(2)函数接口说明;(3)重要的代码行或段落提示。虽然注释有助于理解代码,但注意不可过多地使用注释。参见示例2-6。【规则2-7-1】注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱。注释的花样转载 2014-05-17 20:41:31 · 305 阅读 · 0 评论 -
2.5 长行拆分
【规则2-5-1】代码行最大长度宜控制在70 至80 个字符以内。代码行不要过长,否则眼睛看不过来,也不便于打印。【规则2-5-2】长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。转载 2014-05-17 20:46:40 · 694 阅读 · 0 评论 -
7.4 指针参数是如何传递内存的?
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1 中,Test 函数的语句GetMemory(str, 200)并没有使str 获得期望的内存,str 依旧是NULL,为什么?转载 2014-05-18 10:12:41 · 339 阅读 · 0 评论 -
6.2 返回值的规则
【规则6-2-1】不要省略返回值的类型。C 语言中,凡不加类型说明的函数,一律自动按整型处理。这样做不会有什么好处,却容易被误解为void 类型。C++语言有很严格的类型安全检查,不允许上述情况发生。由于C++程序可以调用C 函数,为了避免混乱,规定任何C++/ C 函数都必须有类型。如果函数没有返回值,那么应声明为void 类型。【规则6-2-2】函数名字与返回值类型在语转载 2014-05-18 09:10:25 · 365 阅读 · 0 评论 -
第 4 章表达式和基本语句索引
读者可能怀疑:连if、for、while、goto、switch 这样简单的东西也要探讨编程风格,是不是小题大做?我真的发觉很多程序员用隐含错误的方式写表达式和基本语句,我自己也犯过类似的错误。表达式和语句都属于C++/C 的短语结构语法。它们看似简单,但使用时隐患比较多。本章归纳了正确使用表达式和语句的一些规则与建议。转载 2014-05-17 20:29:02 · 346 阅读 · 0 评论 -
第 1 章文件结构索引
1.1 版权和版本的声明1.2 头文件的结构1.3 定义文件的结构转载 2014-05-17 16:03:19 · 345 阅读 · 0 评论 -
有关内存的思考题
void GetMemory(char *p){p = (char *)malloc(100);}void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}请问运行Test 函数会有什么样的结果?答:程序崩溃。因为 GetMemory 并不能传递动态内转载 2014-05-17 14:44:30 · 333 阅读 · 0 评论 -
请填写BOOL , float, 指针变量与“零值”比较的 if 语句
提示:这里“零值”可以是0, 0.0 , FALSE 或者“空指针”。例如 int 变量 n 与“零值”比较的 if 语句为:if ( n == 0 )if ( n != 0 )以此类推。()转载 2014-05-17 14:27:32 · 5602 阅读 · 0 评论 -
第 9 章类的构造函数、析构函数与赋值函数索引
构造函数、析构函数与赋值函数是每个类最基本的函数。它们太普通以致让人容易麻痹大意,其实这些貌似简单的函数就象没有顶盖的下水道那样危险。每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数)。对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A 产生四个缺省的函数,如A(void); // 缺省的无参数构造函数转载 2014-05-18 21:25:43 · 399 阅读 · 0 评论 -
第 10 章类的继承与组合索引
对象(Object)是类(Class)的一个实例(Instance)。如果将对象比作房子,那么类就是房子的设计图纸。所以面向对象设计的重点是类的设计,而不是对象的设计。对于 C++程序而言,设计孤立的类是比较容易的,难的是正确设计基类及其派生类。本章仅仅论述“继承”(Inheritance)和“组合”(Composition)的概念。注意,当前面向对象技术的应用热点是COM转载 2014-05-25 17:03:38 · 407 阅读 · 0 评论 -
10.2 组合
【规则10-2-1】若在逻辑上A 是B 的“一部分”(a part of),则不允许B 从A 派生,而是要用A 和其它东西组合出B。例如眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head 应该由类Eye、Nose、Mouth、Ear 组合而成,不是派生而成。如示例10-2-1所示。转载 2014-05-25 17:13:45 · 329 阅读 · 0 评论 -
10.1 继承
如果 A 是基类,B 是A 的派生类,那么B 将继承A 的数据和函数。例如:class A{public:void Func1(void);void Func2(void);};class B : public A{public:void Func3(void);void Func4(void);};main(){B b;b.Func转载 2014-05-25 17:07:21 · 332 阅读 · 0 评论 -
11.3 一些有益的建议
【建议11-3-1】当心那些视觉上不易分辨的操作符发生书写错误。我们经常会把“==”误写成“=”,象“||”、“&&”、“=”这类符号也很容易发生“丢1”失误。然而编译器却不一定能自动指出这类错误。【建议11-3-2】变量(指针、数组)被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。转载 2014-05-25 17:36:09 · 361 阅读 · 0 评论 -
第 11 章其它编程经验索引
11.1 使用const 提高函数的健壮性转载 2014-05-25 17:20:50 · 340 阅读 · 0 评论 -
11.2 提高程序的效率
程序的时间效率是指运行速度,空间效率是指程序占用内存或者外存的状况。全局效率是指站在整个系统的角度上考虑的效率,局部效率是指站在模块或函数角度上考虑的效率。【规则11-2-1】不要一味地追求程序的效率,应当在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率。【规则11-2-2】以提高程序的全局效率为主,提高局部效率为辅。【规则11-2-3转载 2014-05-25 17:34:47 · 409 阅读 · 0 评论 -
9.9 一些心得体会
有些 C++程序设计书籍称构造函数、析构函数和赋值函数是类的“Big-Three”,它们的确是任何类最重要的函数,不容轻视。也许你认为本章的内容已经够多了,学会了就能平安无事,我不能作这个保证。如果你希望吃透“Big-Three”,请好好阅读参考文献[Cline] [Meyers] [Murry]。转载 2014-05-22 21:56:54 · 418 阅读 · 0 评论 -
9.8 如何在派生类中实现类的基本函数
基类的构造函数、析构函数、赋值函数都不能被派生类继承。如果类之间存在继承关系,在编写上述基本函数时应注意以下事项:派生类的构造函数应在其初始化表里调用基类的构造函数。基类与派生类的析构函数应该为虚(即加virtual 关键字)。例如转载 2014-05-22 21:53:37 · 334 阅读 · 0 评论 -
9.7 偷懒的办法处理拷贝构造函数与赋值函数
如果我们实在不想编写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的缺省函数,怎么办?偷懒的办法是:只需将拷贝构造函数和赋值函数声明为私有函数,不用编写代码。例如:class A{ …private:A(const A &a); // 私有的拷贝构造函数A & operate =(const A &a); // 私有的赋值函数};如果有人试图编写如下程序:转载 2014-05-22 21:47:47 · 286 阅读 · 0 评论 -
9.6 示例:类String 的拷贝构造函数与赋值函数
// 拷贝构造函数String::String(const String &other){ // 允许操作other 的私有成员m_data int length = strlen(other.m_data); m_data = new char[length+1]; strcpy(m_data, other.m_data);}// 赋值函数String & String::op转载 2014-05-22 21:45:08 · 494 阅读 · 0 评论 -
8.5 函数内联
8.5.1 用内联取代宏代码转载 2014-05-18 17:32:13 · 338 阅读 · 0 评论 -
9.5 不要轻视拷贝构造函数与赋值函数
由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数有些轻视。请先记住以下的警告,在阅读正文时就会多心:本章开头讲过,如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省的函数就隐含了错误。以类String 的两个对象a,b 为例,假设a.m_data 的内容为“hello”,b.m_data转载 2014-05-18 21:45:25 · 318 阅读 · 0 评论 -
9.1 构造函数与析构函数的起源
作为比C 更先进的语言,C++提供了更好的机制来增强程序的安全性。C++编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙。但是程序通过了编译检查并不表示错误已经不存在了,在“错误”的大家庭里,“语法错误”的地位只能算是小弟弟。级别高的错误通常隐藏得很深,就象狡猾的罪犯,想逮住他可不容易。根据经验,不少难以察觉的程序错误是由于变量没有被正确初始化转载 2014-05-18 21:27:23 · 323 阅读 · 0 评论 -
8.6 一些心得体会
C++ 语言中的重载、内联、缺省参数、隐式转换等机制展现了很多优点,但是这些优点的背后都隐藏着一些隐患。正如人们的饮食,少食和暴食都不可取,应当恰到好处。我们要辨证地看待C++的新机制,应该恰如其分地使用它们。虽然这会使我们编程时多费一些心思,少了一些痛快,但这才是编程的艺术。转载 2014-05-18 17:46:26 · 331 阅读 · 0 评论 -
8.3 参数的缺省值
有一些参数的值在每次函数调用时都相同,书写这样的语句会使人厌烦。C++语言采用参数的缺省值使书写变得简洁(在编译时,缺省值由编译器自动插入)。参数缺省值的使用规则:【规则8-3-1】参数缺省值只能出现在函数的声明中,而不能出现在定义体中。例如:void Foo(int x=0, int y=0); // 正确,缺省值出现在函数的声明中void Foo(int x=0,转载 2014-05-18 17:12:30 · 420 阅读 · 0 评论 -
7.7 杜绝“野指针”
“野指针”不是NULL 指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if 语句很容易判断。但是“野指针”是很危险的,if 语句对它不起作用。“野指针”的成因主要有两种:(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL 指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指转载 2014-05-18 10:33:12 · 380 阅读 · 0 评论 -
以下为Windows NT 下的32 位C++程序,请计算sizeof 的值
char str[] = “Hello” ;char *p = str ;int n = 10;请计算sizeof (str ) =sizeof ( p ) =sizeof ( n ) =void Func ( char str[100]){请计算sizeof( str ) =}void *p = malloc( 100 );转载 2014-05-17 14:31:04 · 3299 阅读 · 0 评论 -
2.3 代码行内的空格
【规则2-3-1】关键字之后要留空格。象const、virtual、inline、case 等关键字之后至少要留一个空格,否则无法辨析关键字。象if、for、while 等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。转载 2014-05-17 16:15:59 · 464 阅读 · 0 评论