1.STL容器共性機制
STL容器所提供的都是值(value)寓意,而非引用(reference)寓意,也就是說當我們給容器中插入元素的時候,容器內(nèi)部實施了拷貝操作,將我們要插入的元素再另行拷貝一份放入容器中,而不是將數(shù)據(jù)元素直接放進容器中,也就是說我們所提供的元素必須能夠被拷貝
- 除了queue和stack之外,每個容器都提供可返回迭代器的函數(shù),運用返回的迭代器就可以訪問元素
- 通常STL不會拋出異常,需要使用者傳入正確參數(shù)
- 每個容器都提供了一個默認的構造函數(shù)和默認的拷貝構造函數(shù)
- 大小相關的構造方法:1 size()返回容器中元素的個數(shù) 2 empty()判斷容器是否為空
#include <iostream>
#include <vector>
using namespace std;
class Teacher{
public:
Teacher(char *name,int age){
int len = strlen(name) + 1;
this->name = new char[len];//在堆分配內(nèi)存
strcpy(this->name,name);
this->age = age;
}
//拷貝構造
Teacher(const Teacher &t){
int len = strlen(t.name) + 1;
this->name = new char[len];
strcpy(this->name,t.name);
this->age = agel
}
//重載=
Teacher& operator=(Teacher &t){
int len = strlen(t.name) + 1;
if (this->name != NULL)
{
delete[] this->name;
}
this->name = new char[len];
strcpy(this->name,t.name);
this->age = agel
return *this;
}
~Teacher(){
if (this->name != NULL)
{
delete[] this->name;
}
this->age = 0;
}
char *name;
int age;
}
//測試函數(shù) 深拷貝和淺拷貝
void test01(){
//會崩潰?。≡蚓褪侵赶騛aaa的有兩個指針,卻只釋放一個,下圖有解
//歸根結底是沒有寫深拷貝的拷貝構造函數(shù)或重載=運算符
Teacher t1("aaaa",19);
vector<Teacher> v;
v.push_back(t1);
}
int main(){
cout<<"hello world..."<<endl;
return 0;
}

1.png
奔潰的原因是由于我們沒有提供拷貝構造函數(shù),沒有重構=操作符,vector對我們的mc對象進行了簡單的淺拷貝,將拷貝的對象插入到容器中,導致我們的mc對象的data指針和容器中mc對象的拷貝對象中的data指針都指向了我們在堆內(nèi)存分配的內(nèi)存,當函數(shù)結束,兩個對象都調(diào)用了析構函數(shù),先調(diào)用析構函數(shù)的對象成功釋放了堆區(qū)內(nèi)存,后調(diào)用析構函數(shù)的對象一釋放,程序就掛掉了。
原因在于兩個指針指向了同一塊堆區(qū)內(nèi)存,這樣會導致不可預知的結果,函數(shù)結束其中一個調(diào)用析構函數(shù),銷毀data指向的內(nèi)存空間,而另一個對象析構的時候回掛掉
問題的解決辦法就是,給我們的對象提供一個拷貝構造函數(shù),并且重構=操作符,兩個指針分別指向自己的那一塊內(nèi)存,互不影響。

2.png
2.STL容器使用時機
| - | vector | deque | list | set | multiset | map | multimap |
|---|---|---|---|---|---|---|---|
| 典型內(nèi)存結構 | 單端數(shù)組 | 雙端數(shù)組 | 雙向鏈表 | 二叉樹 | 二叉樹 | 二叉樹 | 二叉樹 |
| 可隨機存取 | 是 | 是 | 否 | 否 | 否 | 對key而言:是 | 否 |
| 元素搜尋速度 | 慢 | 慢 | 非常慢 | 快 | 快 | 對Key而言:快 | 對key而言:快 |
| 元素安插移除 | 尾端 | 頭尾兩端 | 任何位置 | - | - | - | - |
- vector的使用場景:比如軟件歷史操作記錄的記錄,我們經(jīng)常查看歷史記錄,比如上一次記錄,上上次記錄,但卻不會去刪除記錄,因為記錄是事實的描述。
- deque的使用場景:比如派對購票系統(tǒng),對排隊著的存儲可以采用deque,支持頭端快速移除,尾端的快速添加。如果采用vector,則頭端移除時,會移動大量數(shù)據(jù),速度慢。
vector與deque的比較
- vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的開始位置卻是不固定的。
- 如果有大量釋放操作的話,vector花的時間更少,這跟二者的內(nèi)部實現(xiàn)有關
- deque支持頭部的快速插入和快速移除,這是deque的優(yōu)點
- list的使用場景:比如公交車乘客的存儲,隨時可能有乘客下車,支持頻繁的不確定位置元素的移除插入
- set的使用場景:比如對手機游戲的個人得分記錄的存儲,存儲要求從高分到低分的順序排序
- map的使用場景:比如按ID號存儲十萬個用戶,想要快速要通過ID查找對應的用戶。二叉樹的查找效率,這時就體現(xiàn)出來了。如果是vector容器,最壞情況下可能要遍歷整個容器才能找到該用戶