轉換爲ANSI/ISO 標準c++

    最近在複習C++,也注意到了 C++ 11新標準的一些動向,微軟的msdn也推出了一系列的《welcome back to modern C++ 》的文章,用C++之父Stroustrup的話說,“C++ 11 像一門全新的語言”,(其實真有,D語言基本就是全新的C++微笑),去年研一,花了一個暑假,把《C++ primer plus》厚厚的一本書完完整整地看完了,之後對C++產生了無限的興趣,這裏主要是把《C++ primer plus》後面附錄的一篇好文章摘錄如下,算是我隔了好久,重新開始寫新的博文 :

1.1 使用一些預處理器編譯指令的替代品

1.1.1使用const而不是#define來定義常量

        C使用預處理器來創建常量的符號名稱:

#define MAX_LEN


        C++ 推薦使用const變量來替代:

const  int  MAX_LEN =100;

        使用const的方法優點很多:首先,使用#define時,必須在數字後面加各種後綴來指出除char,int或double之外的類型。例如 ,使用100L表示long 類型;使用3.14F表示float類型。更重要的是,相比#define,const可很方便的用於複合類型,如:

const  int base_vals[]={100,200,300,400,500};
const string ans[3]={"yes","no ","maybe "};

        此外,const標識符遵循變量的作用域規則,因此,可以創建作用域爲爲全局,名稱空間或數據塊常量。不必擔心其定義與程序的其他地方使用的全局變量衝突,如下面的代碼:

#define n 5
const int dz =12;
...
void  fizzle()
{
 	int n;  //ERROR:預處理器將把此處替換爲 int 5 
	int dz;
...
}


        最後,相比C語言中的const,C++版本的const變量默認爲內部鏈接性,這意味着,可將const定義放在工程中的各種文件使用的頭文件中而不會產生編譯錯誤,更多const的用法可以看這裏

        當然在控制何時編譯頭文件方面,#define編譯指令仍然很有幫助:

//blooper.h
#ifndef _BLOOPER_H_
#define _BLOOPER_H_
// code goes here
#endif


        另外,在有一組相關的整型常量時--使用枚舉enum類型可能是更好的選擇

enum{LEVEL1=1, LEVE2=2,L EVEL3=4, LEVEL4=8};


1.1.2 使用inline而不是#define來定義小型函數

        在創建類似於內聯函數的東西時,傳統的C語言方式是使用一個#define宏定義:

#define Cube(X) X*X*X

        這將導致預處理器進行文本置換,而由於不是真正的傳遞參數,因此使用這種宏常常導致意外、錯誤的結果:

y=Cube(x) ;
y=Cube(x+ z++); // 替換出錯,得加大量的括號來避免,如:
#define Cube(x) ((x)*(x)*(x)) //注意,Z++的問題還是不能解決


 

        C++是用inline關鍵字來標識內聯函數,C++內聯函數可以是常規函數,也可以是類方法;

        #define宏的一個優點是,它是無類型的,可任意替換;但這一點可以通過創建內聯模板來使函數獨立於類型,同時傳遞參數。

1.2 使用函數原型

         注意:C++中,函數原型是必不可少的;

        應儘量在函數原型和函數頭中使用const,具體的說,對於表示不可修改的數據的指針參數和引用參數,應儘量使用const。這不僅使編譯器能夠捕獲修改數據的錯誤,也使函數更爲通用。也就是說,接受const指針或引用的函數能夠同時處理const數據和非const數據,而不使用const指針或引用的函數只能處理非const的數據。

1.3類型轉換

        Stroustrup對C語言的抱怨之一就是其無規律可循的類型轉換操作符,此外C語言不能防止將一種類型的指針轉換爲另一種完全不相干的類型指針,這也是極不安全的。而標準的C++提供了新的嚴格類型轉換操作符:

dynamic_cast
static_cast
const_cast
reinterpret_cast


        這方面,《C++ primer plus》基本上講的非常不清楚,《C++編程思想》把概念進一步解釋的更清楚些。

        因此,在執行涉及到指針的類型轉換時,應儘可能使用上述操作符之一。這樣做不但可以指出類型轉換的目的,並可以檢查類型轉換是否按照預期的那樣使用的。

1.4 逐漸熟悉C++特性

        如果使用的是malloc()和free(),請改用new和delete;如果是使用setjmp()和longjmp() ,(說實話,這個還真沒用過,C語言學的,太汗了~)處理錯誤,則請改用try、throw 、和catch。另外,對於表示true和false的值,應將其類型聲明爲bool。

1.5使用新的頭文件

        注意:除了名稱的改變,相比老式頭文件,則應當改用新名稱。這樣做不僅僅是形式上的改變,因爲新版本有時增加了新的特性。另外,新的頭文件包含名稱空間。

1.6使用名稱空間

    

1.7使用autoptr模板   

        每個new都應與delete配對使用。如果使用new的函數由於引發異常而提前結束,將導致問題。使用autoptr對象跟蹤new創建的對象將自動完成delete操作。

1.8使用string類

        傳統的C風格字符串深受不是真正的類型之苦。可以將字符串存儲在字符數組中,也可以將字符數組初始化爲字符串。但不能使用賦值操作符將字符串賦給字符串,而必須使用strcpy()或strncpy()。不能關係操作符來比較C風格字符串,而必須使用strcmp() (使用操作符倒是不會出現句法錯誤,程序將比較字符串的地址,而不是字符串的內容)。

        而string類使得能夠使用對象來表示字符串,並定義了賦值操作符、關係操作符和加法操作符(用於拼接)。此外,string類還提供了自動內存管理功能。不會提前出現字符串截短的情況。

        string類不僅提供了一組設計良好的方法來處理與字符串相關的工作(如查找子字符串)。而且與STL兼容,因此可將STL算法用於string對象。

1.9使用STL

         一個明顯的好處是,如用你聲明一個double或者string對象數組,不如創建vector<double>對象或者vector<string>對象。這樣做的好處與使用string對象類似。賦值操作符已被定義,因此可以使用賦值操作符將一個vector對象賦給另一個vector對象。內置的內存管理功能使得當使用pushback()方法在vector對象中添加元素時,其大小將自動調整。當然,還可以根據實際需要來使用其他有用的類方法和通用算法。

        如果需要鏈表、雙端隊列(或隊列)、堆棧 、常規隊列、集合或者映射,應使用STL,它提供了有用的容器模板。算法庫使得可以將矢量的內容輕鬆地複製到鏈表中,或將集合的內容同矢量比較。這種設計使得STL成爲一個工具箱,它提供了基本部件,可以根據自己的需求進行裝配。

        在設計內容廣泛的算法庫時,效率是一個主要的設計目標,因此只需要完成少量的編程工作,便可以得到最好的結果。另外,實現算法時用到了迭代器的概念,這意味着這些算法不僅可以用於STL容器,也可以用於傳統的數組。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章