vector 的數據安排以及操作方式,與array常常相似,兩者的唯一差別在于空間運用的靈活性:array是靜態空間,一旦配置了不能改變。vector動態空間,可以根據需要,自行擴充空間以容納新元素。
vector的實現技術關鍵在于其對大小控制以及重新配置時的數據移動效率。因為重新申請內存,拷貝原數據,釋放原vector是要花很長時間。所以在滿載時,申請新空間的大小要在空間和時間上取出平衡。
vector結構很簡單:
vector.png
template <typename T>
class Vector
{
......
typedef allocator<T> dataAlloc;
private:
T* _start;
T* _finish;
T* _end_of_storage;
}
迭代器
typedef T* iterator;
typedef const T *const_iterator
原生指針就可以充當迭代器。
添加元素
push_back(const T &value)
- 有空間則直接用 construct 構造元素。
- 沒有空間則先重新分配新的內存,然后再把以前的元素拷貝之后,構造元素。也是因此,迭代器會失效
if (size() == capacity())
reallocateAndCopy();
dataAlloc::construct(_finish++, value);
insert(iterator position, const size_type n, const T &value)
- 備用空間足夠
2 種情況:- a: 插入點后現有元素個數 >= 新增元素個數
- b: 插入點后現有元素個數 <= 新增元素個數
- 備用空間不足
- 第一步:將原vector [ _start, position )拷貝至新的 vector
- 第二步:構造n個value
- 第三步:將 [ position, _finish )元素也拷貝至新的 vector
- 第四步:析構并釋放原vector
/* 備用空間足夠 */
if (_end_of_storage - _finish >= n) {
size_type elems_after = _finish - position;
iterator old_finish = _finish;
if (elems_after > n) {
/* 插入點后現有元素個數 >= x新增元素個數 */
uninitialized_copy(position, old_finish - n, old_finish);
_finish += n;
} else {
/* 插入點后現有元素個數 <= x新增元素個數 */
uninitialied_fill_n(_finish, n - elems_after, value);
_finish += n - elems_after;
uninitialized_copy(position, old_finish, _finish);
_finish += elems_after;
fill(position, old_finish, value);
}
}
/* 備用空間不夠 */
else {
size_type old_size = size();
size_type len = old_size + max(old_size, n); // 新長度為舊長度的2倍,或者舊長度+新元素個數
iterator new_start = dataAlloc::allocate(len);
iterator new_finish = new_start;
try{
/* 將原 vector[_start, position) 拷貝至新的vec */
new_finish = uninitialized_copy(_start, position, new_start);
/* 構造 n 個value */
new_finish = uninitialied_fill_n(new_finish, n, value);
/* 將 [position, _finish) 元素也拷貝過來 */
new_finish = uninitialized_copy(position, _finish, new_finish);
} catch(...) {
destory(new_start, new_finish);
dataAlloc::deallocate(new_start, len);
throw;
}
/* 析構并釋放原vector */
destroyAndFree();
_start = new_start;
_finish = new_finish;
_end_of_storage = _start + len;
}
備用空間足夠,插入點后現有元素個數 <= 新增元素個數.png
修改容量
resize
- n > capacity()需要重新分配內存空間,復制原size()元素,釋放原資源,增加(n - size())個元素
- size() < n <= capacity 不需要重新分配內存空間,增加(n - capacaity())個元素
- n == size() 什么都不做
- n < size() 需要析構(size() - n)個元素
void resize(size_type n, const T &value) {
if (n > capacity()) {
size_type addElementLength = n - size();
/* 重新分配內存 */
T *newStart = dataAlloc::allocate(n);
T *newFinish = uninitialized_copy(begin(), end(), newStart);
/* 拷貝元素 */
newFinish = uninitialied_fill_n(newFinish, addElementLength, value);
/* 銷毀原內存 */
destroyAndFree();
/* 更新相關指針 */
_start = newStart;
_finish = newFinish;
_end_of_storage = _start + n;
} else if (n <= capacity() && n > size()) {
size_type addElementLength = n - size();
_finish = uninitialied_fill_n(end(), addElementLength, value);
} else if (n < size()) {
dataAlloc::destroy(begin() + n, end());
_finish = _start + n;
}
}
reserve
- n > capacity() 重新分配內存空間,復制原size()元素,釋放原資源。
void reserve(size_type n) {
if (n > capacity()) {
T *new_start = dataAlloc::allocate(n);
T *new_finish = uninitialized_copy(begin(), end(), new_start);
destroyAndFree();
_start = new_start;
_finish = new_finish;
_end_of_storage = _start + n;
}
}
刪除元素
void pop_back()
void Vector<T>::pop_back() {
dataAlloc::destroy(--_finish);
}
iterator erase(iterator first, iterator last)
size_type remove_element_counts = last - first; // 要刪除的個數
if (remove_element_counts > 0) {
auto it = first;
for (; last != _finish; last++, it++)
*it = *last;
dataAlloc::destroy(it, _finish);
_finish = _finish - remove_element_counts;
}
return first;
iterator erase(iterator first, iterator last).png
iterator erase(iterator position)
return erase(position, position + 1);