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;
}