c/c++高质量编程学习

高质量编程技巧

编写目的:

       初入公司开始真正的程序员的生活,为了便于交流,希望自己写的程序可以被别人采纳,为了自己以后的发展故在这里学习一下林锐博士的《c/c++高质量编程》。

第一章:文件结构

  C++/C程序的文件以”.h”为后缀,C程序的定义文件以”.c”为后缀,C++程序的定义文件通常以”.cpp”为后缀也有一些系统以”.cc””.cxx”为后缀。

       在头文件(.h)和实现(.cpp定义)的时候要写好版权和版本的声明主要内容由四个组成:

(1)  版权信息

(2)  文件名称,标识符,摘要

(3)  当前版本号,作者/修改者,完成日期

(4)  版本历史信息。

如下:

/*

*copyright(c) 2001 ,什么公司

*All rights reserved

*

*文件名称 filename.h

*文件标识:见配置管理计划书

*摘要:简要描述本文件的内容

*

*当前版本:1.1

*作者:输入作者(或修改者)名字

*完成日期:

*

*取代版本1.0

*原作者:

*完成日期:

*/

1、头文件的结构(.h):

(1)头文件开头处的版权和版本声明

(2)预处理块。(ifndef/define/endif

(3)函数和类结构声明等。

规则1:为了防止文件被重复引用,应当用ifndef/define/endif结构产生预处理块。

规则2#include <filename.h>引用标准库的头文件(编译器将从标准库目录开始搜索)。

规则3#include “filename.h”引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。

规则4:头文件中只存放“声明”而不存放“定义”。

如下:

// 版权和版本声明见示例1-1,此处省略。

 

#ifndef GRAPHICS_H  // 防止graphics.h被重复引用

#define GRAPHICS_H

 

#include <math.h>       // 引用标准库的头文件

#include “myheader.h”      // 引用非标准库的头文件

void Function1(…); // 全局函数声明

class Box               // 类结构声明

{

};

#endif

 

2、定义文件的结构(.cpp

(1)定义文件开头处的版本和版本声明

(2)对一些头文件的引用

(3)程序的实现体

如下:

// 版权和版本声明见示例1-1,此处省略。

 

#include “graphics.h”  // 引用头文件

 

// 全局函数的实现体

void Function1(…)

{

}

 

// 类成员函数的实现体

void Box::Draw(…)

{

}

 

第二章 程序的版式

1、空行:

       (1)规则1:在第个类声明之后、每个函数定义结束之后都要加一个空行

       (2)规则2:在一个函数内逻辑密切的相关语句不要加空行,其它要加空行。

       (3)规则3:一行代码只做一件事

       (4)规则4:ifforwhiledo等语句自占一行,执行语句不得紧跟其后。

       (5)规则5:尽可能在定义变量时初始化变量(就近原则)

2、空格:

       (1)规则1:关键字后要留空格。

       (2)规则2:函数名之后不要留空格,紧跟左括号,以与关键字区别。

       (3)规则3:“,”之后要留空格,“;”不是一行的结束符后要有空格

                     例:for (int i=0; i<MAX; i++){}

       (4)规则4:赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符等              二元操作符后的前后要加空格。

       (5)规则5:一元操作符如“!”,“~”,“++”,“&”等前后不加空格。

3、对齐:

       (1)规则1:左右括号对齐

4、注释:

       (1)规则1:注释放在代码的上方或右方,不可以放在下方。

       (2)规则2:当代码跨行多时应该在最后一个括号的时候写清楚是什么的结束。

5、命名规则:

       (1)规则1:Window是“大小写”混排方式,而Unix应用程序的标识是“小写加                  下划线”的方式。

       (2)规则2:变量的字句应当使用“名词”或者“形容词+名词”。

       (3)规则3:函数的名字应当使用“动词”或者“动词+名词”。在类中成员函数应              当只使用“动词”,被省略掉的名词就是对象本身。

       (4)规则4:类名和函数名用大写字母开头的单词组合而成。

       (5)规则5:变量和参数用小写字母开头的单词组合而成。

       (6)规则6:常量全用大写的字母,用下划线分割单词。

       (7)规则7:静态变量加前缀s_(表示static.

       (8)规则8:全局变量用g_(表示global)

       (9)规则9:类的数据成员加前缀m_表示(member)这样可以避免数据成员与成             员函数的参数同名。

      

第四章 表达式和基本语句

1、布尔变量与零值比较:

       不可将布尔变量直接与TRUEFALSE或者10进行比较。应该用:

       If(flag)if(!flag)

2、整型变量与零值比较:

       应当将整型变量用“==”“!=”直接与0比较。

3、浮点变量与零值比较:

       不可将浮点变量用“==”或“!=”与任何数字比较。应该用:

       If((x>=-EPSIONON)&&(x<=EPSINON))

4、指针变量与零值比较

       应当将指针变量用“==”或“!=”与NULL比较。

5、if语句的判断:

       应该用if(NULL==P)这样可以避免比较错误

6、循环语句的效率:

       1)在多重循环中,如果有可能,应当将最长的循环放在量内层,最短的循环放在最外              层,以减少cpu跨切循环层的次数。

       2)如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体外面。              因为放在内部逻辑判断会打断循环“流水线”作业。效率不高。

 

 

 

 

第五章       常量

1、  const #define 的比较

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

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

2、类中的常量:

       Const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因  为类可以创建多个对象,不同的对象基const数据成员的值可以不同。

       不能在类声明中初始化const数据成员。

       错误:

       Class A

       {

              Const int SIZE =100;//错误:企图在类声明中初始化const数据成员

       }

       Const数据成员的初始化只能在类构造函数的初始化表中进行

       Class A

       {

              A(int size);//构造函数

              Const int SIZE;

       }

       A::A(int size):SIZE(size)//构造函数的初始化表

       {……

       }    

       A a(100);//对象aSIZE值为100

       以上就是常理在类中的使用,不同对象有不同的常量的原因

       要建立在整个类中都恒定的常量,别指望const数据成员了,应该用类中的枚举常量来实现例如:

       Class A

       {

              Enum{SIZE1 = 100, SIZE2 = 200};//枚举常量

              Int array1[SIZE1];

              Int array1[SIZE2];

       };

       枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:        它的隐含数据类型是整数,其最大值有限,且不能表示浮点数

 

 

 

 

 

 

 

 

第六章

       函数接口的两个要素是返回值和参数。

1、  参数的规则:

       规则1:如果参数是指针,且仅作为输入用,则应在类型前加const,以防止该指          针在函数体内被意外修改。

       例:void StringCopy(char* strDestination,const char* strSource);

       规则2:如果输入参数以值传递的方式传递对象,则宜用(const TypeName& 参数          )方式来传递,这样可以省去临时对象的构造和析构过程,从而提高效率。

2、  函数内部实现规则:

       规则1:在函数的“入口处”,对参数的有效性进行检查,要会使用assert(断言)。

       规则2:在函数返回是不可以返回“栈内存”即在函数内开辟的“指针”和“引用”,   因为该内存在函数体结束时被自动销毁。要考虑return的语句效率。

3、  使用断言:

       断言assert仅在Debug中起作用的宏,assert(false)会报警。

4、  引用与指针的比较

       引用的规则:

1)  引用被创建的时候必须被初始化。

2)  引用不能有NULL引用,引用必须与合法的存储单元关联(指针是可以是NULL)。

3)  一旦引用被初始化,就不能改变引用的关系(指针则可以改变所指对象)。

 

 

第七章

1、内存分配方式:

       1)从静态存储区域分配。内存在程序编译的时候就把空间分配好了,这块内存空间                     在整个程序运行时都存在,例:static 变量

       2)在栈上创建。在执行函数里,函数内部变量都可以在栈上创建,函数执行结束时              他们会变释放。栈内分配运算内置于处理器的指令集中,效率很高,但是分配的                     内存容量有限。

       3)从堆上分配,亦称动态内存分配。程序在运行的时候用mallocnew申请任意                 多少的内存,程序员自己负责在何时用freedelete释放内存。

2、内存错误:

       规则1:内存分配后要初始化。

       规则2:内存用完要释放

       规则3:释放了内存不可以使用,return 不要返回指向“栈内存”的“指针”

       规则4:释放后没有将指针设置为NULL。导致产生“野指针”。

       规则5:用mallocnew申请内存后,应该立即检查指针是否为NULL防止使用指针值为NULL的内存。

       规则6:不要忘记为数组和动态内存赋初值。

       规则7:动态内存的申请与释放必须配对。

3、指针与数组的对比:

       数组要么在静态存储区被创建,要么在栈上被创建。数组名对应着一块内存,基地址与容量在生命期内保持不变,只有数组的内容可以改变。

       指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

4malloc/freenew/delete的区别

       Malloc 使用的时候不会调用构造函数而new

       Free  使用的时候不会调用析构函数而delete

       new 数组时要delete[] 指针数组

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值