1. 程式人生 > >C++學習:list容器詳解(一)

C++學習:list容器詳解(一)

list容器詳解

      首先說說STL

 

      STL就是Standard Template Library,標準模板庫。這可能是一個歷史上最令人興奮的工具的最無聊的術語。從根本上說,STL是一些“容器”的集合,這些“容器”有list,vector,set,map等,STL也是演算法和其他一些元件的集合。這裡的“容器”和演算法的集合指的是世界上很多聰明人很多年的傑作。

       STL的目的是標準化元件,這樣就不用重新開發,可以使用現成的元件。STL現在是C++的一部分,因此不用額外安裝什麼。它被內建在你的編譯器之內

。因為STL的list是一個簡單的容器,所以我打算從它開始介紹STL如何使用。如果你懂得了這個概念,其他的就都沒有問題了。另外,list容器是相當簡單的,我們會看到這一點。

       STL容器可以儲存物件,內建物件和類物件。它們會安全的儲存物件,並定義我們能夠操作的這個物件的介面。放在蛋架上的雞蛋不會滾到桌上。它們很安全。因此,在STL容器中的物件也很安全。

       STL演算法是標準演算法,我們可以把它們應用在那些容器中的物件上。這些演算法都有很著名的執行特性。它們可以給物件排序,刪除它們,給它們記數,比較,找出特殊的物件,把它們合併到另一個容器中,以及執行其他有用的操作。 
      STL iterator就象是容器中指向物件的指標

。STL的演算法使用iterator在容器上進行操作。Iterator設定演算法的邊界 ,容器的長度,和其他一些事情。舉個例子,有些iterator僅讓演算法讀元素,有一些讓演算法寫元素,有一些則兩者都行。 Iterator也決定在容器中處理的方向。
       你可以通過呼叫容器的成員函式begin()來得到一個指向一個容器起始位置的iterator。你可以呼叫一個容器的 end() 函式來得到過去的最後一個值(就是處理停在那的那個值)。

       這就是STL所有的東西,容器、演算法、和允許演算法工作在容器中的元素上的iterator。 演算法以合適、標準的方法操作物件,並可通過iterator得到容器精確的長度。一旦做了這些,它們就在也不會“跑出邊界”。 還有一些其他的對這些核心元件型別有功能性增強的元件,例如函式物件。我們將會看到有關這些的例子,現在 ,我們先來看一看STL的list。

       1. 定義一個list
#include <string>
#include <list>
int main (void)
{
 list<string> Milkshakes;
 return 0;
}

      這就行了,你已經定義了一個list。簡單嗎?list<string> Milkshakes這句是你聲明瞭list<string>模板類的一個例項,然後就是例項化該類的一個物件。但是我們別急著做這個。在這一步其實你只需要知道你定義了一個字串型別的list。你需要包含提供STL list類的標頭檔案#include <list>,注意iostream.h這個標頭檔案已經被STL的標頭檔案放棄了,所以可以不用這個標頭檔案。

      注:在Linux中可以用 g++ test1.cpp -o test1 來編譯這個測試程式。

      2. 使用list的成員函式push_back和push_front插入一個元素到list中:

      現在我們有了一個list容器,我們可以使用它來裝東西了。我們將把一個字串加到這個list裡。有一個非常重要的東西叫做list的值型別。值型別就是list中的物件的型別。在這個例子中,這個list的值型別就是字串,string ,這是因為這個list用來放字串。
#include <string>
#include <list>

int main (void)
{
 list<string> Milkshakes; //聲明瞭list<string>模板類的一個例項
 Milkshakes.push_back("Chocolate"); //例項化
 Milkshakes.push_back("Strawberry");
 Milkshakes.push_front("Lime");
 Milkshakes.push_front("Vanilla");
 return 0;
}

        我們現在有個4個字串在list中。list的成員函式push_back()把一個物件放到一個list的後面,而 push_front()把物件放到前面。我通常把一些錯誤資訊push_back()到一個list中去,然後push_front()一個標題到list中, 這樣它就會在這個錯誤訊息以前列印它了。

 

      3. list的成員函式empty()

       知道一個list是否為空很重要。如果list為空,empty()這個成員函式返回真。 我通常會這樣使用它。通篇程式我都用push_back()來把錯誤訊息放到list中去。然後,通過呼叫empty() 我就可以說出這個程式是否報告了錯誤。如果我定義了一個list來放資訊,一個放警告,一個放嚴重錯誤, 我就可以通過使用empty()輕易的說出到底有那種型別的錯誤發生了。 
      我可以整理這些list,然後在列印它們之前,用標題來整理它們,或者把它們排序成類。

     /**************************************************************
      //    Using a list to track and report program messages and status

#include <iostream.h>
#include <string>
#include <list>
int main (void)
{
 #define OK 0
 #define INFO 1
 #define WARNING 2
 int return_code;
 list<string> InfoMessages;
 list<string> WarningMessages;

 // during a program these messages are loaded at various points
 InfoMessages.push_back("Info: Program started");
 // do work...
 WarningMessages.push_back("Warning: No Customer records have been found");
 // do work...

 return_code = OK;

 if (!InfoMessages.empty()) {
  // there were info messages
  InfoMessages.push_front("Informational Messages:");
  // ... print the info messages list, we'll see how later
  return_code = INFO;
 }

 if (!WarningMessages.empty()) {
  // there were warning messages
  WarningMessages.push_front("Warning Messages:");
  // ... print the warning messages list, we'll see how later
  return_code = WARNING;
 }

 // If there were no messages say so.
 if (InfoMessages.empty() && WarningMessages.empty()) {
  cout << "There were no messages " << endl;
 }

 return return_code;
}

******************************************************************/

     4.用for迴圈來處理list中的元素

     我們想要遍歷一個list,比如列印一個list中的所有物件來看看list上不同操作的結果。要一個元素一個元素的遍歷一個list, 我們可以這樣做:

       

 

      這個程式定義了一個iterator(類似指標),MilkshakeIterator。我們把它指向了這個list的第一個元素。 這可以呼叫Milkshakes.begin()來做到,它會返回一個指向list開頭的iterator。然後我們把它和Milkshakes.end()的 返回值來做比較,當我們到了那兒的時候就停下來。
  容器的end()函式會返回一個指向容器的最後一個位置的iterator。當我們到了那裡,就停止操作。 我們不能不理容器的end()函式的返回值。我們僅知道它意味著已經處理到了這個容器的末尾,應該停止處理了。 所有的STL容器都要這樣做。
  在上面的例子中,每一次執行for迴圈,我們就重複引用iterator來得到我們列印的字串。

 

         在STL程式設計中,我們在每個演算法中都使用一個或多個iterator。我們使用它們來存取容器中的物件。 要存取一個給定的物件,我們把一個iterator指向它,然後間接引用這個iterator。
  這個list容器,就象你所想的,它不支援在iterator加一個數來指向隔一個的物件。 就是說,我們不能用Milkshakes.begin()+2來指向list中的第三個物件,因為STL的list是以雙鏈的list來實現的, 它不支援隨機存取。vector和deque(向量和雙端佇列)和一些其他的STL的容器可以支援隨機存取。

  上面的程式打印出了list中的內容。任何人讀了它都能馬上明白它是怎麼工作的。它使用標準的iterator和標準 的list容器。沒有多少程式設計師依賴它裡面裝的東西, 僅僅是標準的C++。這是一個向前的重要步驟。這個例子使用STL使我們的軟體更加標準。

 

https://blog.csdn.net/hao95165/article/details/52931992