1.盡量用const 和inline 而不用#define
1)例:#define ASPECT_RATIO 1.653
在源碼進(jìn)入編譯器之前,預(yù)編譯指令會被處理器去掉,直接用1.653代替ASPECT_RATIO,如果涉及到這個(gè)常量的代碼出錯(cuò),若想由1.653追蹤到原指令會很困難
所以,這種情況下一般用const double ASPECT_RATIO=1.653代替。
定義指針時(shí),需要把指針和指向的變量都定義成const
const char * const authorName ="YLang"
2)有些編譯器,類內(nèi)只允許初始化整數(shù)類型(int,bool,char)還只能是常量
若在類內(nèi)分開聲明數(shù)組和數(shù)組大小,為避免某些編譯器的不足,采用enum枚舉的方式
enum{NUM_TURNS=5};//直接采用 const NUM_TURNS=5; 對于某些禁止此行為的編譯器來說,會出現(xiàn)編譯錯(cuò)誤;
int scores[NUM_TURNS];
3)#define 宏的用法
例:最大值算法
#define max(a,b) ((a)>(b)?(a):(b))//每個(gè)參數(shù)必須加括號
在遇到自加時(shí),表現(xiàn)了很大的不穩(wěn)定性。
int a=5,b=0;
max(++a,b);//a的值增加了2次
max(++a,b+10);//a的值只增加了1次
采用inline函數(shù)來替換該宏。
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 不是安全類型,沒有擴(kuò)展性,并且把要讀寫的變量和控制讀寫格式信息分開。
重載運(yùn)算符<< 彌補(bǔ)了他們的缺點(diǎn)。
<iostream>可移植性可擴(kuò)展性較高,庫類有構(gòu)造函數(shù);<stdio.h>庫類沒有構(gòu)造函數(shù)
#include <iostream> 和#include <iostream.h>的區(qū)別
前者得到的是置于std名字空間下的元素,后者是同樣的元素,但是全局空間里,會造成命名沖突。
3.盡量用new和delete而不是malloc 和free
前者會創(chuàng)建/刪除對象,同時(shí)調(diào)用構(gòu)造/析構(gòu)函數(shù);后者僅創(chuàng)建/刪除空間,沒有調(diào)用構(gòu)造/析構(gòu)函數(shù);
4.C++注釋風(fēng)格
盡量不要用/* */
5.new和delete要對應(yīng)相同的形式
new數(shù)組用了[] ,delete也必須用[];
如果要?jiǎng)h除指針指向的數(shù)組空間需要用delete[];
6.盡量在析構(gòu)函數(shù)里對指針成員調(diào)用delete
除非類成員最初用了new,否則是不用在析構(gòu)里用delete的。
或者用智能指針來代替(C++標(biāo)準(zhǔn)庫auto_ptr)\
7.預(yù)先準(zhǔn)備好內(nèi)存不足的情況
考慮到當(dāng)new一個(gè)對象時(shí),理論上可能會發(fā)生無法完成內(nèi)存分配而拋出異常的情況。
C的做法是定義宏來分配內(nèi)存并檢查分配是否成功。
這種宏的C++再現(xiàn):
#define NEW(PTR,TYPE)
try {(PTR)= new TYPE;}
catch(std::bad_alloc&){assert(0);}
//說明:
//1)assert檢查傳給它的表達(dá)式是否為非零,如果不是非0,發(fā)出一條錯(cuò)誤信息并調(diào)用abort.
// 而assert只是在調(diào)試狀態(tài)(沒有定義 NDEBUGE)下才會起作用,產(chǎn)品發(fā)布時(shí)(定義 NDEBUGE)assert什么都不做。
//2)沒有考慮到new的多種形式: new T;new T(constructor argument);new T[size];
所以一般不用這種方案
簡單的方法:制定一錯(cuò)誤處理函數(shù),在拋出異常前調(diào)用。
在頭文件<new>中,
typedef void (* new_handler)();
new_handler set_new_handler()(new_handler p) throw();
在調(diào)用new之前,使用set_new_handler來設(shè)定錯(cuò)誤處理函數(shù),傳入?yún)?shù)為函數(shù)指針。
例:
void onMemoryError(){......}//invoke before throwing the expection;
int mail()
{
set_new_handler(onMemoryError);
int *pBigMemory=new int[100000];
}
C++ 中處理機(jī)制:
設(shè)定處理函數(shù)為全局,在set_new_handler安裝自定義處理函數(shù)之前保存原有函數(shù)。
分配內(nèi)存,若失敗則拋出異常,返回之前恢復(fù)原處理函數(shù)。
void * X::operator new(size_t size)
{
new_handler globalHandler = // 安裝X 的new_handler
std::set_new_handler(currentHandler);
void *memory;
try
{ // 嘗試分配內(nèi)存
memory = ::operator new(size);
}
catch (std::bad_alloc&)
{
// 恢復(fù)舊的new_handler
std::set_new_handler(globalHandler);
throw; // 拋出異常
}
std::set_new_handler(globalHandler); // 恢復(fù)舊的new_handler
return memory;
}