1、使用 const 提高函式的健壯性
(1)用const 修飾函式的引數
(1.1)如果輸入引數採用「指標傳遞」,那麼加const 修飾可以防止意外地改動該指標,起到保護作用。
(1.2)如果輸入引數採用「值傳遞」,由於函式將自動產生臨時變數用於複製該引數,該輸入引數本來就無需保護,所以不要加const 修飾。
(1.3)對於非內部資料型別的引數而言,象 void func(a a) 這樣宣告的函式注定效率比較底。因為函式體內將產生a 型別的臨時物件用於複製引數a,而臨時物件的構造、複製、析構過程都將消耗時間。為了提高效率,可以將函式宣告改為void func(a &a),因為「引用傳遞」僅借用一下引數的別名而已,不需要產生臨時物件。但是函式void func(a &a) 存在乙個缺點:「引用傳遞」有可能改變引數a,這是我們不期望的。
解決這個問題很容易,加const修飾即可,因此函式最終成為void func(const a &a)。
以此類推,是否應將void func(int x) 改寫為void func(const int &x),以便提高效率?完全沒有必要,因為內部資料型別的引數不存在構造、析構的過程,而複製也非常快,「值傳遞」和「引用傳遞」的效率幾乎相當。
(2)用const 修飾函式的返回值
(2.1)如果給以「指標傳遞」方式的函式返回值加const 修飾,那麼函式返回值(即指標)的內容不能被修改,該返回值只能被賦給加const 修飾的同型別指標。
例如函式
const char * getstring(void);
如下語句將出現編譯錯誤:
char *str = getstring();
正確的用法是
const char *str = getstring();
(2.2)如果函式返回值採用「值傳遞方式」,由於函式會把返回值複製到外部臨時的儲存單元中,加const 修飾沒有任何價值。
例如不要把函式int getint(void) 寫成const int getint(void)。
同理不要把函式a geta(void) 寫成const a geta(void),其中a 為使用者自定義的資料型別。
如果返回值不是內部資料型別,將函式a geta(void) 改寫為const a & geta(void)的確能提高效率。但此時千萬千萬要小心,一定要搞清楚函式究竟是想返回乙個物件的「拷貝」還是僅返回「別名」就可以了,否則程式會出錯。
(2.3)函式返回值採用「引用傳遞」的場合並不多,這種方式一般只出現在類的賦值函式
中,目的是為了實現鏈式表達。
(3)const 成員函式
任何不會修改資料成員的函式都應該宣告為const 型別。如果在編寫const 成員函式時,不慎修改了資料成員,或者呼叫了其它非const 成員函式,編譯器將指出錯誤,這無疑會提高程式的健壯性。
2、提高程式的效率
(1)不要一味地追求程式的效率,應當在滿足正確性、可靠性、健壯性、可讀性等質量因素的前提下,設法提高程式的效率。
(2)以提高程式的全域性效率為主,提高區域性效率為輔。
(3)在優化程式的效率時,應當先找出限制效率的「瓶頸」,不要在無關緊要之處優化。
(4)先優化資料結構和演算法,再優化執行**。
(5)有時候時間效率和空間效率可能對立,此時應當分析那個更重要,作出適當的折衷。例如多花費一些記憶體來提高效能。
(6)不要追求緊湊的**,因為緊湊的**並不能產生高效的機器碼。
3、一些有益的建議
(1)當心那些視覺上不易分辨的操作符發生書寫錯誤。我們經常會把「==」誤寫成「=」,像「||」、「&&」、「<=」、「>=」這類符號也很容易發生「丟1」失誤。然而編譯器卻不一定能自動指出這類錯誤。
(2)變數(指標、陣列)被建立之後應當及時把它們初始化,以防止把未被初始化的變數當成右值使用。
(3)當心變數的初值、預設值錯誤,或者精度不夠。
(4)當心資料型別轉換發生錯誤。盡量使用顯式的資料型別轉換(讓人們知道發生了什麼事),避免讓編譯器輕悄悄地進行隱式的資料型別轉換。
(5)當心變數發生上溢或下溢,陣列的下標越界。
(6)當心忘記編寫錯誤處理程式,當心錯誤處理程式本身有誤。
(7)當心檔案i/o 有錯誤。
(8)避免編寫技巧性很高**。
(9)不要設計面面俱到、非常靈活的資料結構。
(10)如果原有的**質量比較好,盡量復用它。但是不要修補很差勁的**,應當重新編寫。
(11)盡量使用標準庫函式,不要「發明」已經存在的庫函式。
(12)盡量不要使用與具體硬體或軟體環境關係密切的變數。
(13)把編譯器的選擇項設定為最嚴格狀態。
(14)如果可能的話,使用pc-lint、logiscope 等工具進行**審查。
4、細節決定成敗
(1)有乙個要特別注意的就是1(數字1)和l(小寫字母l)之間,0(數字0)和o(小寫字母o)之間的區別。
(2)所有巨集定義、列舉常數、唯讀變數全用大寫字母命名,用下劃線分割單詞。
(3)一般來說習慣上用n,m,i,j,k 等表示int 型別的變數;c,ch 等表示字元型別變數;a 等表示陣列;p 等表示指標。當然這僅僅是一般習慣,除了i,j,k 等可以用來表示迴圈變數外,別的字元變數名盡量不要使用。
(4)定義變數的同時千萬千萬別忘了初始化。定義變數時編譯器並不一定清空了這塊記憶體,它的值可能是無效的資料。
(5)不同型別資料之間的運算要注意精度擴充套件問題,一般低精度資料將向高精度資料擴充套件。
(6)sizeof 是關鍵字不是函式
程式設計細節小點
1.碰到字串中比較排序的時候,對數值進行比較的時候,不一定用正規表示式進行匹配是否是數值,然後再比較大小,可以直接用ascii碼進行比較大小。if c 0 c 9 2.將ip掩碼轉換成 long型 格式 string split 255.255.255.0 split listipnums new ...
程式設計細節綜合
console.read 讀取下乙個字元,但是要注意的是,她是依次讀取乙個完整的字串的第乙個字元,他返回的是乙個ascii碼 至少包含兩個字元13 10 如果你想讀取這串數字的所有字元,可以這樣做 while true 注意,這不是乙個無限死迴圈,不是像你們想象的,每輸入乙個,便列印一次,而是,你直...
Unity Shader程式設計細節
1.通用編譯指令 pragma vertex name pragma fragment name 2.cg hlsl的語義,語義是不可省略的,它將告訴系統使用者需要輸入哪些值以及使用者的輸出是什麼。position 告訴unity,把模型的頂點座標輸入 sv position 告訴unity,頂點著...