《C++-C编程指南 ---林锐博士》 学习笔记 (一)
该指南中对很多经常忽略的细节进行了深入的探讨。
细细阅读和思考,逐步建立起自己的比较完备的概念。
一、函数设计
函数接口两个要素是函数参数和函数的返回值
C语言中,函数参数有值传递和指针传递两种方式。
C++语言中,增加了引用传递方式
规则:
1、如果参数是指针,且仅作为输入使用,则应在该类型前面加上const,防止该指针在函数体内被以外修改。
2、如果输入参数一直传递的方式传递对象,则宜改成“const &”方式来传递,可以省去临时对象的构造和析构过程,提高效率。
3、避免函数有太多的参数,参数的个数控制在5个以内。如果参数过多,可以用结构体来封装部分参数。提高参数的可读性。
4、尽量不要使用类型和数目不确定的参数(类型检查)。
5、不要省略函数的返回值类型,无类型时用void替代。
6、正常值和错误标志混在一起返回。 正常值用输入参数获取,错误标志用return语句返回。
函数内部实现的规则:
1、在函数体的入口处,对参数的有效性进行检查。充分理解并正确适使用断言来防止此类的错误。
2、在函数的出口处,对return语句的风趣恶性和效率进行检查。
3、函数功能单一,规模小。无记忆功能,相同的输入产生相同的输出。
4、不仅检查输入参数的有效性,还要检查通过其他途径进入函数体的变量的有效性。如全局变量,文件句柄等。
5、用于出错处理的返回值要清楚。
一般教科书都鼓励程序员进行防错设计,这种设计可能会隐瞒错误。当进行防御性设计时,如果“不可能发生”的事情发生了,则需要使用断言进行报警。
内存管理
内存分配方式有3种
1、静态存储区分配
该区域在程序编译的时候就已经分配好了,这块内存在程序的运行过程中都存在。
如全局变量,static变量。
2、在站上创建
在执行函数时,函数内部的局部变量的存储单元都可以在栈上创建,在函数执行结束时,这些存储单元自动释放。效率高,但分配的内存容量有限。
3、从堆上分配
程序在运行时程序员malloc或new申请的任意多的内存,程序员负责free或delete释放该内存。
常见内存错误即其对策
1、内存分配未成功,却使用了它。
在使用内存值钱检查指针时候为null,如果指针p是函数的参数,那么在函数的路口处用 assert(p!= null)进行检查,如果使用malloc或new来申请内存,应该用if(p==null)或if(p!=null)进行防错处理。
2、内存分配成功,但是为初始化就引用了它。没有初始化的概念,而是误以为内存的缺省初值权威零。
3、内存分配成功并且已经初始化,但操作越过了内存的边界。
4、忘记了释放内存,造成内存的泄露。
5、释放了内存却继续使用了它。
使用free或delete释放内存后,没有将指针设置为null,导致产生了野指针
1、用malloc或new申请内存后,应该立即检查指针值时候为nulll,防止指针值为null的内存。
2、不要忘记为数组和动态内存赋初值,防止将位被初始化的内存作为右值使用。
3、避免数组或指针的小标越界,特别当心发生多1 少1的操作
4、动态内存的申请和释放工作必须配对,防止内存泄露
5、使用free或delete释放内存之后,立即将指针设置为null,防止产生野指针。
附1:类String的成员实现:
class String
{
public:
String(const char *str = NULL);//普通构造函数
String(const String &other); //拷贝构造函数
~String(void); //析构函数
String& operate =(const String &other);//赋值函数
protected:
private:
char *m_data;
};
//析构函数 释放资源
String::~String(void)
{
delete [ ] m_data;
}
String::String(const char *str)
{
if (str==NULL)
{
m_data = new char[1];
*m_data = '/0';
}
else
{
int length=strlen(str);
m_data = new char[length+1];
strcpy(m_data,str);
}
}
String::String(const String &other)
{
int length =strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data,other.m_data);
}
String& String::operate =(const String& other)
{
if(this==&other)
return *this;
int length=strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data,other.m_data);
return *this;
}
附2:strcpy函数的实现:
char *strcpy(char *strDest,const char *strSrc)
{
assert((strDest != NULL ) && (strSrc != NULL)
char *address = strDest;
while((*strDest++=*strSrc++) != ‘/0’)
NULL;
return address;
}