C++ primer(第3章)-閱讀筆記

範圍for語句(range for)

範圍for語句是對給定序列中的每個元素並對序列中的每個值進行某種操作,其語法形式爲:

string str("some string");
// 輸出str中的每個字符
for (auto c : str){
	cout << c << endl ;
}

標準庫類型vector

標準庫類型vector表示對象的集合,其中所有對象的類型都相同。vector容納中其他對象,因此這也被稱爲容器(container)。要使用vector,需要添加適當的頭文件

#include <vector>
using std::vector ;

vector<int> ivec ; // 定義int類型的ivec
vecor<Sales_item> Sales_vec ; // 保存Sales_item類型的對象

這裏,vector<變量類型> 含義爲:vector本質上是一個類模板,編譯器在創建類的過程會對其進行實例化(instantiation),當使用這個模板時,需要指出要把類轉化爲何種類型。換句話說:vector並不是一個數據類型,而是一個模板,因此需要指出vector中元素的類型,例如vector < int >。
下面給出定義與初始化vector對象的樣例

vector<T> v1 ; //T代表實際使用的類或者變量類型
vector<T> v2(n,val); //包含n個重複的元素,每個元素的值都是val
vector<T> v3{a,b,b...} ; //包含了初始值個數的元素,每個元素被賦相應的值
vector<T> v4 = {a,b,c,...}; //等價於v3

注:不能使用下標的形式來添加元素,但是可以通過下標進行元素訪問,看下面的例子

vector<int> ivec;
// ivec[0] = 1; 錯誤,ivec不包含任何元素,還是一個空的vector
ivec.push_back(1);
cout << ivec[0] << endl;
//當這個元素存在的時候,也是可以通過下標來進行值更改的
ivec[0] = 2;
cout << ivec[0] << endl;

迭代器

要訪問string對象或者vector對象的字符,除了使用下標進行訪問之外,還可以使用迭代器
在所有的標準庫的容器中,都可以使用迭代器,但是其中只有少數幾種才同時支持下標運算符。嚴格而言,string對象並不是容器類型,但是string支持很多容器類似的操作。
和指針不一樣的是,獲取迭代器不是取締支付,有迭代器的類型會返回迭代器的成員。這些類型都擁有begin和end的成員,其中begin成員負責返回指向的第一個元素。有如下語句:

auto b = v.begin(); //b表示第一個元素
e = v.end(); //e爲尾元素的下一個位置

若容器爲空,那麼begin和end會返回同一個迭代器,都是尾後迭代器。
迭代器運算符
迭代器中市場使用 == 和 !=來進行判斷

for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it){
	*it = toupper(*it);  //將當前字符轉換成大寫形式
}

泛型編程的概念:我們在for循環中時常使用的是<=判斷結束條件,而迭代器更喜歡使用==和!=。
迭代器類型

vector<int>::iterator it ; //it能讀寫vector<int>中的元素
vector<int>::const_iterator it2 ; //it2只能讀元素,不能寫元素

結合解引用和成員訪問操作

解引用可以獲得迭代器所指向的對象,如果該對象的類型恰好是類,那麼久可能希望進一步訪問他的成員。
例子:一個由字符串組成的vector對象,要檢查其元素是否爲空,則:

(*it).empty()
*it.empty(); //錯位,試圖訪問it的empty成員,但是it是一個迭代器,沒有這個成員

以上,圓括號必不可少,具體含義爲先解引用,再對解引用的結果進行點運算。
c++中,爲了簡化上述操作,定義了箭頭運算符** (->)**。即it->men與(*it).mem表達的意思相同。

某些vector對象的操作會使迭代器實效
雖然vector可以動態的增長,但是有時也會有一些副作用。已知的一個限制是不能在for循環內向vector添加元素。另外,一種是可能改變vector對象容量的操作例如push_back,都會使該vector對象的迭代器實效。

指針和數組

string nums[] = {"a","b", "c"} ;
string *p = $nums[0] ;  //p指向nums的第一個元素
string *p2 = nums; //數組的一個特性是,在一些用到數組名字的地方,編譯器會自動將其替換成一個指向數據首元素的指針
int ia[] = {0,1,3,4,5} ;
auto ia2(ia) ; // ia是一個整型指針,指向ia的第一個元素
ia2 = 42; //錯誤,這是一個指針

指針也是迭代器
就像使用迭代器遍歷vector對象中元素一樣,使用指針也遍歷數組中的元素。
通過數組名或者首元素的地址就可以得到指向首元素的指針,不過,要獲取尾後指針就需要使用數組的一個特殊性質:獲取尾元素後面那個不存在的元素的地址
例如,一個數組有10個元素
那麼

int *e = &arr[10]; //指向arr元素的下一個位置的指針
for(int *b = arr; b != e; ++b){
	cout << *b << endl ;  
}

注:尾後指針不能執行解引用和遞增操作。

下標和指針

int ia[] = {1,2,3,4} ;
int *p = ia ;
a = *(p+2) ; //等價於a = ia[2]
int *p2 = &is[2] ; //指向索引爲2的元素
int k = p[-2] ;  //指向ia[0]的元素
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章