版權聲明:您好,轉載請留下本人部落格的位址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/45069675
(一):學習目标:
1:模闆,包括函數模闆和類模闆
2:容器及其分類,以容器中的資料結構
3:容器vector和疊代器的具體用法
(二):學習
1:函數模闆
/**
* 學習模闆函數
*/
int max(int a,int b){
return a > b?a:b;
}
float max(float a,float b){
return a > b?a:b;
}
char max(char a,char b){
return a > b?a : b;
}
但是類型是比較多的,是以每一個類型都要寫一個這樣的函數的話,肯定是不行的。是以就有了模闆函數。
下面就是模闆函數:
/**
* 上面函數的模闆函數
*/
template<typename T> //或者是 template<class T>
T max(T a,T b){
return a > b?a : b;
}
T代表傳入的類型
那麼如何調用模闆函數呢?
下面就是調用的代碼:
注意:由于在STL裡面max已經被定義了,是以在這裡換一個名稱
下面就是這個的定義和調用的過程
/*
* test.cpp
*
* Created on: 2015年4月15日
* Author: hongb_000
*/
#include <iostream>
using namespace std;
///**
// * 學習模闆函數
// */
//int UIP_Max(int a,int b){
// return a > b?a:b;
//}
//
//float UIP_Max(float a,float b){
// return a > b?a:b;
//}
//
//char UIP_Max(char a,char b){
// return a > b?a : b;
//}
/**
* 上面函數的模闆函數
*/
template<typename T> //或者是 template<class T>
T UIP_Max(T a,T b){
return a > b?a : b;
}
int main(void)
{
//注意這裡的<int>是不能省略的,這裡表示指定輸入的類型
int m = UIP_Max<int>(10,20);
cout << m << endl;
char a = UIP_Max<char>('a','b');
cout << a << endl;
return 0;
}
模闆函數會在運作過程中根據傳入的類型進行替換相應的類型。是以這就實作了模闆函數的功能。
2:模闆類
現在假設我們有兩個個類:
class IMax{
public:
IMax(int _a,int _b){
a = _a;
b = _b;
}
int GetMax(){
return a>b?a:b;
}
private:
int a;
int b;
};
class FMax{
public:
FMax(float _a,float _b){
a = _a;
b = _b;
}
int GetMax(){
return a>b?a:b;
}
private:
float a;
float b;
};
這樣遇到的問題和上面遇到的函數的問題是一樣的,這樣就引入了類模闆。
下面我們寫一下類模闆
template <class T> //或者是 template<typename T>
class CMax{
public:
CMax(T _a,T _b){
a = _a;
b = _b;
}
T GetMax(){
return a > b ? a : b;
}
private:
T a;
T b;
};
與函數模闆的定義差不多,凡是遇到類型的地方全部用T去替代。
那麼如何使用這個類模闆呢?下面我們來試一下:
//這樣這個地方的<int>也是不能省略的,為了指定類型
CMax<int> cMax(10,20);
int p = cMax.GetMax();
cout << p << endl;
類模闆就是建立一個通用的類。
注意:
類模闆可以定義多種類型:
template<typename T1,typename T2>
3:容器的學習
容器是用來存放,管理一組元素的資料集合。
容器的資料結構如下面的圖所示:
容器有序列式的容器和關聯式的容器。
序列式的容器有vector,deque,list
關聯式的容器元素的位置取決于特定的排序的準則,
關聯式的容器有set,multiset等
4:vector的學習
1):vector的簡介
vector是将元素置于一個動态的容器中進行管理,相當于一個動态的數組。
vector可以随機通路内部的資料。
vector尾部的插入和移除元素是比較簡單的,但是在中間是比較複雜的。
2):使用前的準備
#include <vector>
using namespace std;
3):預設的構造
vector<T> vec;
例如:
vector<int> vec; //一個存放int類型的vector容器
vector<float> vec; //一個存放float類型的vector
class CA{};
vector<CA*> vecCA; //用于存放CA的指針
vector<CA> vec; //用于存放CA的對象,不過這裡一定要提供拷貝構造函數
4):vector末尾的添加和移除操作
vector:push_back(ele); //在容器尾部加入一個元素
vector:pop_back(); //移除容器中的最後一個元素
下面是一個測試的例子:
vector<int> vec;
vec.push_back(1);
//在vector後面插入一個元素
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
//将vector的最後一個元素移除
vec.pop_back();
for(size_t i = 0;i < vec.size();i++){
cout << vec.at(i) << " ";
}
輸出結果為:
1 2 3 4
5):vector資料的存取
vector擷取元素有兩種方式:
1:vec.at(i); //但是i越界的話,會跑出out_of_range一場
2:vec[i] //i越界的話沒有異常抛出,直接報錯
6):對元素的修改
vector可以直接對某一個位置的元素進行修改。
例如:
vce.at(2) = 18;
下面是在剛剛那個例子的基礎上進行調整:
//位置3的元素現在是3,我們把她改成19
vec.at(2) = 19;
for(size_t i = 0;i < vec.size();i++){
cout << vec.at(i) << " ";
}
cout << endl;
則輸出結果為:
1 2 3 4
1 2 19 4
7):通路vector的第一個值和最後一個值
int mFront = vec.front(); //第一個值
int mBack - vec.back(); //最後一個值
同時還可以使用這兩個函數對其中的數值進行修改
例如:
我們想把第一個元素改成88:
vec.front() = 88; //這樣就修改成功了
5:疊代器的學習
疊代器相當于一個指向,指向vector中的元素。
疊代器用來周遊容器中的内容,就像是一個指針,指向容器中的某一個位置。
1):疊代器的類别
第一種:輸入疊代器,隻支援一次周遊
第二種:輸出疊代器,隻支援一遍輸入
第三種:正向疊代器,可以進行多次讀寫
第四種:雙向疊代器:就可以往前多次讀寫,又可以往後多次讀寫
第四種:随機通路疊代器:可以除了讀寫之外,還能讀取和輸入任意位置的内容
2):雙向疊代器支援的操作
it++,++it,it–,–it,*it,itA=itB,itA==itB,itA!=itB
其中list.set,multiset,map,multimap支援雙向疊代器
3):随機通路存儲器
在雙向疊代器的操作基礎上添加加了随機功能
it+=i;it = i;it+i;it[i],itA
vector<int> vecA;
vecA.push_back(1);
vecA.push_back(3);
vecA.push_back(5);
vecA.push_back(7);
vecA.push_back(9);
//注意疊代器的寫法
vector<int>::iterator it = vecA.begin();
cout << *it << endl; //輸出應該就是第一個元素的值1
++it; //但是前++要比後++的效率高,因為前++傳回的是一個引用,後++傳回的是一個值
cout << *it << endl; //輸出的應該就是3了
it += 3;
cout << *it << endl; //輸出應該就是9了
當it==vecA.end()的時候,就不能操作*it了,因為現在是最後一個元素的下一個位置
5):使用疊代器進行vector的周遊
/**
* 使用疊代器進行vector的周遊
*/
vector<int>::iterator itA = vecA.begin();
for(;itA != vecA.end();itA++){
cout << *itA << " ";
}
6):反向疊代器
/**
* 反向疊代器,逆序輸出
*
* 其中的vec.rbegin()指向vector指向最後一個元素
* vec.rbegin()指向vector的第一個元素的上一個位置
*/
vector<int>::reverse_iterator rit = vecA.rbegin();
for(;rit != vecA.rend();rit++){
cout << *rit << " ";
}
7):還有兩個
//第一個:vector<T>::const_iterator
//第二個:vector<T>::const_reverse_iterator
是前面講的兩種的隻讀形式。
6:vector帶參數的構造
1):帶疊代器開始和結束的構造
例子:
//參數為疊代器的開始和結束
vector<int> vecB(array,array+5);
vector<int> vecC(vecA.begin(),vecA.end());
2):
vector<int> vecD(3,9); //vector有3個元素,每個元素都是9
7:vector的指派
1):vector:assign(beg,end); //将(beg,end)區間的資料拷貝給本身。左閉右開
2):vector:assign(n,ele); //n個ele元素
3):vector:swap(vec); //将vec與本身進行互換
8:vector的大小
1):vector:size(); //傳回容器元素的個數,傳回 size_z
2):vector:empty(); //傳回容器是否為空
3):vector:resize(num); //重新指定容器的長度為num
4):vector:resize(num,ele); //重新指定容器的長度,超過部分用ele填充,少的部分删除
例如:
vector<int> vecE;
vecE.push_back(1);
vecE.push_back(2);
vecE.push_back(3);
//目前vecE有元素1,2,3
vecE.resize(5); //現在的元素應該為1,2,3,0,0
vecE.resize(8,3); //現在的元素應該為1,2,3,0,0,3,3,3
vecE.resize(2); //現在的元素應該為1,2
8:vector的插入
1):vector:insert(pos,ele); //在pos位置插入一個ele元素的拷貝,傳回新資料的位址
2):vector:insert(pos,n,ele); //在pos位置插入n個ele元素
3):vector:insert(pos,beg,end): //在pos插入[beg,end)區間的元素
例子:
/**
* 插入測試
*/
vector<int> vecF;
vecF.push_back(1);
vecF.push_back(3);
vecF.push_back(5);
vecF.push_back(9);
vector<int> vecG;
vecG.push_back(2);
vecG.push_back(4);
vecG.push_back(6);
vecG.push_back(8);
vecF.insert(vecF.begin(),11); //現在vecF中的元素應該是11,1,3,5,7,9
vecF.insert(vecF.begin()+1,2,33); //現在vecF中的元素應該是 11,33,33,1,3,5,9
//執行之後的元素應該是2,4,6,8,11,33,33,1,3,5,9
vecF.insert(vecF.begin(),vecG.begin(),vecG.end());
9:vector的元素删除
1):vec.clear(); //移除容器中的所有的元素
2):vec.erase(beg,end): //删除[beg,end)區間的元素
3):vec.erase(pos); //删除pos位置的元素,傳回下一個資料的位置
總結:
通過對小節的學習,基本上了解了vector中的資料結構以及其适用方法,不過還是需要多加練習。