天天看點

第十六章

C++類庫(不是内褲)和stl博大精深,我等初學者肯定現在隻有遠觀還不能亵玩了。本節講到stl後面基本就基本隻能算看懂了,估計要真明白會用得專門那本書去學。這章寫到第五節就基本寫不下去了。。。先貼上來留個紀念吧,等以後明白了再回來修改

現在程式設計很少有人重頭編寫了,基本都是直接運用然後部分重寫前輩編寫的代碼。C++的類庫就是為這個設計的。這一章首先從最常見的string類講起。

1.string類

大家現在對string類也該很熟悉了,就是一個處理字元串的類。雖然目的很簡單,但為了應付各種運用,包含的内容也非常多。光是構造函數就有7個,之後C++11又添了兩個。書裡面表16.1和程式清單16.1列出了所有構造函數的用法. 其實這幾種方法無外乎就是怎麼把其他已經存在的string或者char數組,string的一部分,char數組的一部分來用來初始化建立的string。既然string類實質上也是一個char數組,那麼也可以通過[#]來直接調用string的第#個字元。String類也支援+或者指派=操作,也支援cout輸出或者cin輸入。

對于string類,有兩種方式可以輸入

string str;

cin >> str; //隻能讀一個單詞

getline(cin. Str); //讀一行,不包括\n

string類和char數組最大的差別就是string類少了很多對字元串長度的限制,代價就是string類必須包括很多應付這個問題的函數。

但是string類對對象還是有最大允許長度限制的,由常量string:: npos來指定,預設為unsigned int的最大值。

String類也支援比較字元串,包括比較string類字元串和比較char數組字元串,運用起來很簡單: <, =, >就行。這個基本就是比較每個字元的順序。更有意義一點點是确定字數串長度的方法:size(), length()。 這兩個方法作用一樣,支援size()相容STL。

String類還有提高查找字元的方法find(), 可以傳回被查找字元第一次出現的位置。書中給了一個猜單詞的遊戲的例子來說明這個函數。

此外,string類還可以删除字元串的部分或全部内容,用一個字元串的部分或全部内容替換另一個字元串的部分或全部内容,插入或删除資料,等等等等。具體看附錄F

2. 智能指針

智能指針是指行為類似指針的類對象,加以其他功能。什麼時候需要它了,看書中的例子

Void remodel(string & str)

{

       String * ps = newstring(str);

       …..

       Str = ps;

       Return;

}

很明顯,這裡ps沒有delete,但是不是加了delete就沒問題了呢。 如果…..裡面有個exception throw的函數,那麼遇到exception就跳到throw那去了,delete不會執行。使用者也說了,大不了我在try catch裡面也加上delete呗。可是可以,不過這就太麻煩了,而且很多人都會忘記。

但是如果ps是一個類,它自己有一個析構函數,會delete掉指針,那麼就沒問題了。怎麼把ps弄成一個類呢, 有三個智能指針模闆(auto_ptr, unique_ptr, shared_ptr)都可以定義類似指針的對象,可以将new獲得的位址賦給這種對象,當智能指針過期是,其析構函數将使用delete來釋放這些記憶體。

要建立智能指針對象,必須包含頭檔案memory,然後聲明。比如如果是double類的指針:

auto_ptr<double> pd(new double);

unique_ptr<double> pdu(new double);

shared_ptr<double> pds(new double);

用了智能指針就不要再用delete了。聲明之後用法基本跟正常指針用法相同。

Auto_ptr實際上C++11不再支援, 還有這三種指針的差別是什麼了,看下面。

auto_ptr<string> ps1 (new string(“string”));

auto_ptr<string> ps2;

ps2 = ps1;

這時候ps1, ps2都指向同一個string對象,這是不支援的。解決辦法可以是建立所有權概念,對于特定的對象,隻能有一個智能指針可以擁有它和delete它。這就是auto_ptr和unique_ptr的政策。另外一種方案就是建立智能更高的指針,跟蹤引用特定對象的智能指針數,這樣成為引用計數。例如指派時計數加1,指針過期是計數減1.僅當最後一個指針過期是,才調用delete,這是shared_ptr所采用的政策。

應該如何選擇智能指針呢,如果程式要使用多個指向同一個對象的指針,應選擇shared_ptr,這樣的情況包括:有一個指針數組,并使用一些輔助指針來表示特定的元素,比如最大或最小;兩個對象包含都指向第三個對象的指針;STL容器包含指針。如果程式不需要多個執行同一個對象的指針,則可以使用unique_ptr

3. 标準模闆庫STL

标準模闆庫就是聽說過很多次的STL了,standard templatelibrary, 其提供了一組表示容器,疊代器,函數對象和算法的模闆:

容器:一個與數組類似的擔憂,可以儲存若幹個值,stl要求儲存的值必須是一個類型

算法:完成特定任務的方法

疊代器:用來周遊容器的對象

函數對象是類似于函數的對象,可以是類對象或者函數指針。

總的來說STL能夠構造各種容器(包括數組,隊列和連結清單),然後執行各種操作,包括搜尋排序等

STL一個很簡單的例子就是我們學過的vector類,用法很簡單:

vector<int>ratings(5); 這樣就建立了一個包含5個int資料的vector對象了,之後對象的用法跟普通數組類似。

如果到這裡就結束了那建立這個vector類完全可以用普通數組代替。vector必然還有其他功能了。vector包含了STL容器都提供的一些基本方法,包括size() – 傳回容器中元素數目,swarp()-交換兩個容器的内容,等等。

疊代器怎麼用了,首先它可以是指針,也可以是一個可以執行類似指針操作-如解除引用或者遞增。先看怎麼聲明:

vector<int>::iteratorpd; 這樣就聲明了一個給容器vector的int類型對象的疊代器。之後我們就可以

pd =ratings.begin(); //将pd指向ratings的第一個元素

*pd = 22.3;//給pd指向的對象指派

++pd; //将pd指向下一個元素

可以看出來疊代器和指針有很大的相似。

此外書中還介紹了在隊列末尾插入新值得push_back()操作,删除摸個區間元素的erase()方法,或者添加元素的方法。

STL還從更廣泛角度定義了很多非成員函數來執行諸如搜尋,排序,随機排序等操作,有點這些函數與STL類的成員函數重名,要注意區分。

書中舉了三個這樣的函數for_each(), random_shuffle(), sort(). 我覺得現在也肯定記不住他們的用法,但一定得知他們的存在。有意思的怎麼用sort來對對象或者結構排序,方法就是要重載運算符<來決定怎麼來比較對象或者結構的大小

4 泛型程式設計

泛型程式設計和面向對象程式設計不同,泛型程式設計關注的是算法,目的是編寫獨立于資料類型的代碼。C++中的模闆就是泛型程式設計的基礎。

首先再來看看疊代器,書裡面說疊代器是了解STL的關鍵說在,因為它可以使算法獨立于使用的容器類型。為什麼這麼說呢。書裡面舉了一個查找元素并傳回的find()函數的例子。這個函數要求不僅能獨立于容器中存儲的資料類型,而且獨立于容器本身的資料結構。模闆可以滿足前者,而疊代器可以作為周遊容器中的值得通用表示。這是因為疊代器可以:

可以執行解除引用的操作,以便能夠範圍它引用的值

能夠将一個疊代器賦給另一個

能夠使用疊代器周遊容器中的是以元素

那麼我們現在可以首先對每個容器類定義相應的疊代器類型,可以實作*和++之類的。使用容器類是,就不需要疊代器怎麼實作的,隻需知道有這麼一個東西,begin()傳回第一個元素,end()傳回最後一個元素,等等。

不同算法對疊代器的要求不同,例如有的算法隻需要讀取資料,有的則需要修改。STL定義了五種疊代器:輸入疊代器,輸出疊代器,正向疊代器,雙向疊代器和随機範圍疊代器。是以疊代器都可以執行解除引用操作,也可以進行比較。下面看疊代器的不同

輸入疊代器:

可以通過解除引用來讀取容器的值,但不能修改。輸入疊代器是單通行疊代器,可以遞增,但不能倒退

輸出疊代器:

隻能通過解除引用來修改容器的值,但不能讀取。也是單通行。

正向疊代器:

隻使用++來周遊容器,但總是按相同的順序周遊一系列值。即可以能夠讀取和修改資料,也可以隻能讀取資料。

雙向疊代器:

具有正向疊代器的所有特性,同時支援遞減運算符

随機通路疊代器:

顧名思義,就是可以通路容器任意位置的元素。

那麼問題來了,要這麼多疊代器幹嘛,有一個随機通路疊代器不就行了麼。答案是為了在編寫算法盡可能使用要求最低的疊代器,并讓他适用于容器的最大區間。其實說白了就是一個效率問題了。

STL提供了一下預定義疊代器,使用時需包含頭檔案iterator

說實話看到這裡基本看不懂了,平時基本沒有接觸這些方面的應用,是以看起來很吃力。先了解吧,到以後遇到實力的時候再回過頭來看。

既然疊代器都有不同種類,那麼容器也應該有了,C++過去有11個種類dequei,list,queue, priprity_queue, stack, vector, map, multimap, set, multiset 和bitset,後來C++11有增添了幾種。。。。現在我隻能在這裡說,每個容器都有自己存在的原因。。。

5. 函數對象

函數對象又叫函數符functor,是可以以函數方式與()結合使用的任意對象,包括函數名,指向函數的制作和重載了()運算符的類對象。

該節剩下的就開始介紹了很多函數符概念,非常拗口,也不好了解,我短時間也想不出來照抄之外的解釋了。。是以這裡就不抄書了。