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

一、头文件结构:
(1)头文件开头处的版权和版本声明。
(2)预处理块。
(3)函数和类结构声明等。
为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。

#include<filename.h>//引用标准库的头文件(编译器直接将从标准库目录开始搜索)
#include"filename.h"//引用非标准库的头文件(编译器将从用户的工作目录开始搜索)

头文件中只存放“声明”而不存放“定义”

二、程序版式:
(1)空行:各函数块之间、函数体内逻辑不密切的语句之间均应加空行分隔。
(2)空格:二元操作符前后均留空格。关键字之后要留空格,象const、virtual、inline、case等关键字之后至少要留一个空格,用于辨析关键字;象if、for、while等关键字之后应留一个空格再跟左号‘(’,以突出关键字。部分“,”、“;”后也要留一个空格。
(3)长行适度拆分。
(4)修饰符:*和&应紧靠变量名,避免歧义。
三、命名规则:
(1)类名和函数名:用大写字母开头的单词组合而成,函数名不能同时用作变量名。
(2)变量名:应当使用“名词”或者“形容词+名词”,定义后应当初始化,防止产生随机值。
习惯性地,n、i、j、k表示整型循环变量,c、ch表示字符变量,a表示数组,p、q表示指针变量
全局函数名:应当使用“动词”或者“动词+名词”(动宾词组)。
类的成员函数:应当只使用“动词”,被省略掉的名词就是对象本身。
(3)变量和参数用小写字母开头的单词组合而成。常量全用大写的字母,用下划线分割单词。静态变量加前缀s_(表示static)。
四、表达式和基本语句
1、if语句中各类型变量与零值比较
(1)bool类型:true(非零)/false(0)

bool flag;
f(flag);//表示flag为真
f(!flag)//表示flag为假

2)int类型:

int a = 1;
if(a == 0);
if(a != 0);

3)浮点类型:注意精度限制

double/float x;
f((x >= -EPSINON)&&(x <= EPSINON))//EPSINON是允许的误差(即精度)

(4)指针类型:

if(p == NULL);//p与NULL显式比较,强调p是指针变量
if(p != NULL);
if(NULL == p);//与if(p == NULL)与意义相同,但此写法易于避免或发现由于输入粗心产生的问题

对于二者比较并需返回其中一值,可直接:return 三元运算表达式
2、循环语句
效率――降低循环体复杂性
(1)多重循环中,尽量最外侧为最长循环。
(2)逻辑判断尽量在循环之外。
循环变量
(1)不可在for循环体内修改循环变量,防止for循环失去控制。
(2)for语句的循环控制变量的取值尽量采用“半开半闭区间”写法。
3、goto语句:随意跳转,需少用、慎用

五、常量――标识符
易修改,提高可读性
1、const与#define:
(1)const:有数据类型,编译时会安全检查,调试
(2)宏常量:无数据类型,仅字符替换,编译预处理时
类内const完全取代宏常量
2、位置:头文件中(公开),定义文件的头部(隐藏)。

六、函数设计
1、函数的接口设计
函数接口的两个要素:参数、返回值
函数接口传递方式:值传递、指针传递
1)、参数
(1)避免太多,书写完整,命名恰当,顺序合理
(2)指针且仅作输入:const,防止该指针在函数体内被任意修改
(3)输入参数以值传递方式传递对象:const &,省去临时对象构造与析构,提高效率
2)、返回值
(1)将错误标志用return语句返回,void类型也需声明
(2)函数名称与返回值类型语义上不可冲突
(3)返回对象合理选择传递方式,考虑效率
http://blog.csdn.net/u014114990/article/details/51007136

2、函数的内部实现规则
1)、函数“入口处”检查参数有效性;“出口处”检查return语句正确性与效率
2)、return语句不可返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数结束时自动销毁
3)、功能单一,规模要小,少用static局部变量

3、断言
使用断言assart(仅在Debug中起作用的宏),检查“不该发生”的情况

4、引用与指针
1)、引用即别名,权限小于指针,指针可代替引用
2)、引用创建同时必须初始化,指针任意时间
3)、引用必须与合法存储单元连用,指针可为NULL
4)、引用不可改变引用关系,指针可随意改变所指对象
引用传递 (int &p)
指针传递 (int *p)

七、第七章
一、内存分配方式
1、 从静态存储区域分配
内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
2、在栈上创建
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3、从堆上分配,亦称动态内存分配
程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

二、常见内存错误
http://blog.csdn.net/vcayi/article/details/1636491

三、指针与数组
1、两者在含义上的区别:
数组对应着一块内存区域,而指针是指向一块内存区域。其地址和容量在生命期里不会改变,只有数组的内容可以改变;而指针却不同,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错
2、计算内存容量的区别:
用运算符sizeof可以计算出数组的容量(字节数),而用sizeof却无法计算指针所指内存的容量,用sizeof(p)得到的结果永远是4或者2(即指针变量所占内存单元的字节数,一般情况下指针变量占2个或4个字节的内存单元)。在进行参数传递时,数组会自动退化为同类型的指针

四、指针参数传递内存:
“指向指针的指针”
函数返回值传递动态内存

五、关于动态内存
动态内存分配(Dynamic Memory Allocation):就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小
main()结束后会自动释放malloc()的内存的,监控者是操作系统,但需养成良好编程习惯

六、关于“野指针”
指向“垃圾”内存的指针
原因:
(1)普通指针,未初始化、
(2)动态内存分配,释放后未置NULL、
(3)操作超越变量范围

七、内存
1、内存分配与释放
1)、malloc/free
malloc函数原型是:void* malloc(unsigned int size);
(1)malloc函数的主要作用是在内存中分配一个长度为size的连续存储空间。其返回值是一个指向分配空间的起始位置的指针。如果分配失败,将返回NULL。
(2)如果要为类型为stuct node的结构分配一块内存空间,可以使用一下语句来实现:p=(struct node*)malloc(sizeof(struct node));
sizeof(struct node)表示计算 结构体类型需要占用的字节数,struct node*是将函数的返回值类型void*转换为指向结构体指针类型类型
如果分配成功,把该内存区域的起始地址返回给指针p

free函数原型是:void free(void *p);
free函数的作用是释放p指向的内存空间(实时回收内存)。如free(p)
注:函数malloc和free一般是成对使用,成对出现的,在使用完内存后,采用free进行释放;
使用函数malloc时,最好要测试是否分配成功;
已经释放掉的内存不可以重新使用
2)、new/delete
new用法:
(1)开辟单变量地址空间
new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址,int *a = new int 即为将一个int类型的地址赋值给整型指针a
int *a = new int(5) ;//作用同上,但是同时将整数赋值为5
(2)开辟数组空间
一维: int *a = new int[100];开辟一个大小为100的整型数组空间
二维: int **a = new int[5][6]
三维及其以上:依此类推.
一般用法: new 类型 [初值]
delete用法:
(1) int *a = new int;
delete a; //释放单个int的空间
(2)int *a = new int[5];
delete [] a; //释放int数组空间
要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.
用new和delete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它
3)、区别
(1)malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符
(2)new能够自动分配空间大小
(3)对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++需要一个能对对象完成动态内存分配和初始化工作的运算符new,以及一个能对对象完成清理与释放内存工作的运算符delete—简而言之 new/delete能进行对对象进行构造和析构函数的调用进而对内存进行更加详细的工作,而malloc/free不能
4)、联系
既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete,malloc/free必须配对使用

8、关于内存耗尽
1)、判断指针:为NULL,return语句中指本函数或者exit()终止本程序
2)、对内存分配函数设置异常处理函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值