STL實踐指南上

2021-03-31 08:56:57 字數 3980 閱讀 7596

譯者注

這是一篇指導您如何在microsoft visual studio下學習stl並進行實踐的文章。這篇文章從stl的基礎知識講起,循序漸進,逐步深入,涉及到了stl編寫**的方法、stl**的編譯和除錯、命名空間(namespace)、stl中的ansi / iso字串、各種不同型別的容器(container)、模板(template)、游標(iterator)、演算法(algorithms)、分配器(allocator)、容器的巢狀等方面的問題,作者在這篇文章中對讀者提出了一些建議,並指出了使用stl時應該注意的問題。這篇文章覆蓋面廣,視角全面。不僅僅適合初學者學習stl,更是廣大讀者使用stl程式設計的實踐指南。

stl簡介

stl (標準模版庫,standard template library)是當今每個從事c++程式設計的人需要掌握的一項不錯的技術。我覺得每乙個初學stl的人應該花費一段時間來熟悉它,比如,學習stl時會有急劇公升降的學習曲線,並且有一些命名是不太容易憑直覺就能夠記住的(也許是好記的名字已經被用光了),然而如果一旦你掌握了stl,你就不會覺得頭痛了。和mfc相比,stl更加複雜和強大。

stl有以下的一些優點:

背景知識

寫這一部分是讓一些初學計算機的讀者在富有挑戰性的電腦科學領域有乙個良好的開端,而不必費力地了解那無窮無盡的行話術語和沉悶的規則,在這裡僅僅把那些行話和規則當作stler們用於自娛的創造品吧。

使用**

本文使用的**在stl實踐中主要具有指導意義。

一些基礎概念的定義

模板(template)——類(以及結構等各種資料型別和函式)的巨集(macro)。有時叫做甜餅切割機(cookie cutter),正規的名稱應叫做范型(generic)——乙個類的模板叫做范型類(generic class),而乙個函式的模板也自然而然地被叫做范型函式(generic function)。

stl——標準模板庫,一些聰明人寫的一些模板,現在已成為每個人所使用的標準c++語言中的一部分。

容器(container)——可容納一些資料的模板類。stl中有vector,set,map,multimap和deque等容器。

向量(vector)——基本陣列模板,這是乙個容器。

游標(iterator)——這是乙個奇特的東西,它是乙個指標,用來指向stl容器中的元素,也可以指向其它的元素。

hello world程式

我願意在我的**時間在這裡寫下我的程式:乙個hello world程式。這個程式將乙個字串傳送到乙個字元向量中,然後每次顯示向量中的乙個字元。向量就像是盛放變長陣列的花園,大約所有stl容器中有一半是基於向量的,如果你掌握了這個程式,你便差不多掌握了整個stl的一半了。

//程式:vector演示一

//目的:理解stl中的向量

// #include "stdafx.h" -如果你使用預編譯的標頭檔案就包含這個標頭檔案

#include // stl向量的標頭檔案。這裡沒有".h"。

#include // 包含cout物件的標頭檔案。

using namespace std;  //保證在程式中可以使用std命名空間中的成員。

char* szhw = "hello world"; 

//這是乙個字元陣列,以」/0」結束。

int main(int argc, char* argv)

// push_back函式將資料放在向量的尾部。

// 將向量中的字元乙個個地顯示在控制台

for (vi=vec.begin(); vi!=vec.end(); vi++) 

// 這是stl迴圈的規範化的開始——通常是 "!=" , 而不是 "<"

// 因為"<" 在一些容器中沒有定義。

// begin()返回向量起始元素的游標(iterator),end()返回向量末尾元素的游標(iterator)。

// 使用運算子 「*」 將資料從游標指標中提取出來。

cout << endl;  // 換行

return 0;}

push_back是將資料放入vector(向量)或deque(雙端佇列)的標準函式。insert是乙個與之類似的函式,然而它在所有容器中都可以使用,但是用法更加複雜。end()實際上是取末尾加一(取容器中末尾的前乙個元素),以便讓迴圈正確執行——它返回的指標指向最靠近陣列界限的資料。就像普通迴圈中的陣列,比如for (i=0; i<6; i++) ——ar[6]是不存在的,在迴圈中不會達到這個元素,所以在迴圈中不會出現問題。

stl的煩惱之一——初始化

stl令人煩惱的地方是在它初始化的時候。stl中容器的初始化比c/c++陣列初始化要麻煩的多。你只能乙個元素乙個元素地來,或者先初始化乙個普通陣列再通過轉化填放到容器中。我認為人們通常可以這樣做:

//程式:初始化演示

//目的:為了說明stl中的向量是怎樣初始化的。

#include // 和相同

#include

using namespace std;

int ar[10] = ;

char* str = "hello world";

int main(int argc, char* argv)

在程式設計中,有很多種方法來完成同樣的工作。另一種填充向量的方法是用更加熟悉的方括號,比如下面的程式:

//程式:vector演示二

//目的:理解帶有陣列下標和方括號的stl向量

#include

#include

#include

using namespace std;

char* szhw = "hello world";

int main(int argc, char* argv)

for (i=0; i

這個例子更加清晰,但是對游標(iterator)的操作少了,並且定義了額外的整形數作為下標,而且,你必須清楚地在程式中說明為向量分配多少記憶體空間。

命名空間(namespace)

1.用using關鍵字使用這個命名空間,在檔案的頂部,但在宣告的標頭檔案下面加入:

using namespace std;

這對單個工程來說是最簡單也是最好的方法,這個方法可以把你的**限定在std命名空間中。

2.使用每乙個模板前對每乙個要使用的物件進行宣告(就像原形化):

using std::cout;

using std::endl;

using std::flush;

using std::set;

using std::inserter;

儘管這樣寫有些冗長,但可以對記憶使用的函式比較有利,並且你可以容易地宣告並使用其他命名空間中的成員。

3.在每一次使用std命名空間中的模版時,使用std域識別符號。比如:

typedef std::vector

vec_str;

這種方法雖然寫起來比較冗長,但是是在混合使用多個命名空間時的最好方法。一些stl的狂熱者一直使用這種方法,並且把不使用這種方法的人視為異類。一些人會通過這種方法建立一些巨集來簡化問題。

除此之外,你可以把using namespace std加入到任何域中,比如可以加入到函式的頭部或乙個控制迴圈體中。

一些建議

為了避免在除錯模式(debug mode)出現惱人的警告,使用下面的編譯器命令:

#pragma warning(disable: 4786)

另一條需要注意的是,你必須確保在兩個尖括號之間或尖括號和名字之間用空格隔開,因為是為了避免同「>>」移位運算子混淆。比如

vector > veclis;

這樣寫會報錯,而這樣寫:

vector > veclis;

就可以避免錯誤。

(待續)

STL實踐指南(上)

譯者注 這是一篇指導您如何在microsoft visual studio下學習stl並進行實踐的文章。這篇文章從stl的基礎知識講起,循序漸進,逐步深入,涉及到了stl編寫 的方法 stl 的編譯和除錯 命名空間 namespace stl中的ansi iso字串 各種不同型別的容器 contai...

STL實踐指南

stl實踐指南 作者 jeff bogan 介紹這是一篇指導您如何在microsoft visual studio下學習stl並進行實踐的文章。這篇文章從stl的基礎知識講起,循序漸進,逐步深入,涉及到了stl編寫 的方法 stl 的編譯和除錯 命名空間 namespace stl中的ansi is...

STL實踐指南 一

stl簡介 背景知識 一些基礎概念的定義 hello world程式 stl的煩惱之一 初始化 命名空間 namespace 一些建議 另一種容器 集合 set 所有的stl容器 stl簡介 返回top stl 標準模版庫,standard template library 是當今每個從事c 程式設...