1.定義vector
vector的定義分為四種
(1)vector()? ?——————無參構造
(2)vector(size_t n,const value_type& val = value_type())? ?——————構造并初始化n個val
(3)vector(const vector& v1) ———————拷貝構造
(4)vector(inputiterator first,inputiterator last) ————使用迭代器進行初始化
代碼模擬實現:
namespace c_simplystudy:
{
template<class T>
class vector
{
public:vector(){_start = nullptr;_finish = nullptr;_endOfStorage = nullptr;}vector(int n, const T& value = T()):_start(new T[n]),_finish(_start+n),_endOfStorage(_finish){for (int i = 0; i < n; i++){*(_start + i) = value;}}
template<class InputIterator>vector(const vector<T>& v):_start(nullptr),_finish(nullptr), _endOfStorage(nullptr){reverse(v.capacity());iterator it = begin();const iterator last = cbegin();while (it != last){*it++ = *last++;}_finish = it;}vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}
private:
iterator _start; // 指向數據塊的開始
iterator _finish; // 指向有效數據的尾
iterator _endOfStorage; // 指向存儲容量的尾
};
}
2.vector迭代器的使用與空間增長控制
迭代器:
?(1)begin()————獲取第一個數據位置的iterator/const_iterator
?(2)end()————獲取最后一個數據的下 一個位置的iterator/const_iterator
?(3)rbegin()————獲取最后一個數據位置的reverse_iterator
?(4)rend()————獲取第一個數據前一個位置的reverse_iterator
空間增長:
?(1)size()————獲取數據個數
?(2)capacity()————獲取容器容量
不同的編譯器下,容器“滿了”時,擴容的規則不同,在VS下是按1.5倍增長的,g++則是按2倍增長
?(3)empty()————判空
?(4)reserve()————改變capacity
reserve只負責開辟空間,如果確定知道需要用多少空間,reserve可以緩解vector增容的代 價缺陷問題
?(5)resize(n,val)————改變size(n為改變后的size,val為用于初始化的值)
如果n<size,則size=n,不進行初始化;如果n>capacity,則擴容至n,并且將未初始化的數據初始化為val
3.vector增刪查改
?(1)push_back()————尾插
?(2)?pop_back()————尾刪
?(3)find()————查找
如果存在則返回位置
?(4)insert()————插入
?(5)erase()————刪除
?(6)swap()————交換兩個vector
?(7)operate[]————下標索引
4.vector迭代器失效
vector的增刪會導致迭代器失效——實際就是迭代器底層對應指針所指向的空間被銷毀了,而使用一塊已經被釋放的空間,造成的后果是程序崩潰(即如果繼續使用已經失效的迭代器,程序可能會崩潰)
迭代器失效有兩種情況:
(1)當 it 用vector.begin()初始化后,如果對vector進行增或者可能會導致其擴容的操作,則vector在擴容時會釋放掉舊空間,begin()會指向新空間,而這里的 it 卻仍指向被釋放掉的舊空間,此時用 it 進行迭代器操作則會發生迭代器失效
int main()
{vector<int> v{1,2,3,4,5};auto it=v.begin();v.reserve(100); //通過擴容使迭代器失效while(it != v.end()){cout << *it << " ";++it;} //vs下會直接崩潰return 0;
}
(2)繼續將 it 用vector中的迭代器進行初始化,如果使用erase將 it 指向的迭代器刪除掉,則 it 指向的迭代器會失效,如果仍然對 it 進行解引用,則會發生報錯;erase刪除pos位置元素后,pos位置之后的元素會往前搬移,沒有導致底層空間的改變,理 論上講迭代器不應該會失效,但是:如果pos剛好是最后一個元素,刪完之后pos剛好是end 的位置,而end位置是沒有元素的,那么pos就失效了。因此刪除vector中任意位置上元素 時,vs就認為該位置迭代器失效了
#include <vector>
#include <algorithm>
int main()
{vector<int> v{1,2,3,4,5};vector<int>::iterator it = find(v.begin(), v.end(), 3);v.erase(it);while(it != v.end()){cout << *it << " ";++it;} //因為空間還是原來的空間,后序元素往前搬移了,it的位置還是有效的//erase刪除的迭代器如果是最后一個元素,刪除之后it已經超過end// 此時迭代器是無效的,++it導致程序崩潰return 0;
}
(此問題在string中也會出現,而且如果在linux環境下運行程序,由于g++編譯器對于迭代器失效的檢測并不嚴格,所以當迭代器失效后,對失效后的迭代器進行引用并不會報錯,但是運行結果已經不同)
迭代器失效解決方法 :在使用前,對迭代器重新賦值