1.尽量用const 和inline 而不用#define
1)例:#define ASPECT_RATIO 1.653
在源码进入编译器之前,预编译指令会被处理器去掉,直接用1.653代替ASPECT_RATIO,如果涉及到这个常量的代码出错,若想由1.653追踪到原指令会很困难
所以,这种情况下一般用const double ASPECT_RATIO=1.653代替。
定义指针时,需要把指针和指向的变量都定义成const
const char * const authorName ="YLang"
2)有些编译器,类内只允许初始化整数类型(int,bool,char)还只能是常量
若在类内分开声明数组和数组大小,为避免某些编译器的不足,采用enum枚举的方式
enum{NUM_TURNS=5};//直接采用 const NUM_TURNS=5; 对于某些禁止此行为的编译器来说,会出现编译错误;
int scores[NUM_TURNS];
3)#define 宏的用法
例:最大值算法
#define max(a,b) ((a)>(b)?(a):(b))//每个参数必须加括号
在遇到自加时,表现了很大的不稳定性。
int a=5,b=0;
max(++a,b);//a的值增加了2次
max(++a,b+10);//a的值只增加了1次
采用inline函数来替换该宏。
inline int max(int a,int b) {return a>b?a:b;}
template<class T>
inline const T& max(const T& a, const T& b)
{ return a>b?a:b;}
2.尽量用<iostream>而不是<stdio.h>
scanf/printf 不是安全类型,没有扩展性,并且把要读写的变量和控制读写格式信息分开。
重载运算符<< 弥补了他们的缺点。
<iostream>可移植性可扩展性较高,库类有构造函数;<stdio.h>库类没有构造函数
#include <iostream> 和#include <iostream.h>的区别
前者得到的是置于std名字空间下的元素,后者是同样的元素,但是全局空间里,会造成命名冲突。
3.尽量用new和delete而不是malloc 和free
前者会创建/删除对象,同时调用构造/析构函数;后者仅创建/删除空间,没有调用构造/析构函数;
4.C++注释风格
尽量不要用/* */
5.new和delete要对应相同的形式
new数组用了[] ,delete也必须用[];
如果要删除指针指向的数组空间需要用delete[];
6.尽量在析构函数里对指针成员调用delete
除非类成员最初用了new,否则是不用在析构里用delete的。
或者用智能指针来代替(C++标准库auto_ptr)\
7.预先准备好内存不足的情况
考虑到当new一个对象时,理论上可能会发生无法完成内存分配而抛出异常的情况。
C的做法是定义宏来分配内存并检查分配是否成功。
这种宏的C++再现:
#define NEW(PTR,TYPE)
try {(PTR)= new TYPE;}
catch(std::bad_alloc&){assert(0);}
//说明:
//1)assert检查传给它的表达式是否为非零,如果不是非0,发出一条错误信息并调用abort.
// 而assert只是在调试状态(没有定义 NDEBUGE)下才会起作用,产品发布时(定义 NDEBUGE)assert什么都不做。
//2)没有考虑到new的多种形式: new T;new T(constructor argument);new T[size];
所以一般不用这种方案
简单的方法:制定一错误处理函数,在抛出异常前调用。
在头文件<new>中,
typedef void (* new_handler)();
new_handler set_new_handler()(new_handler p) throw();
在调用new之前,使用set_new_handler来设定错误处理函数,传入参数为函数指针。
例:
void onMemoryError(){......}//invoke before throwing the expection;
int mail()
{
set_new_handler(onMemoryError);
int *pBigMemory=new int[100000];
}
C++ 中处理机制:
设定处理函数为全局,在set_new_handler安装自定义处理函数之前保存原有函数。
分配内存,若失败则抛出异常,返回之前恢复原处理函数。
void * X::operator new(size_t size)
{
new_handler globalHandler = // 安装X 的new_handler
std::set_new_handler(currentHandler);
void *memory;
try
{ // 尝试分配内存
memory = ::operator new(size);
}
catch (std::bad_alloc&)
{
// 恢复旧的new_handler
std::set_new_handler(globalHandler);
throw; // 抛出异常
}
std::set_new_handler(globalHandler); // 恢复旧的new_handler
return memory;
}