vector容器的底層實現基於數組,裏面封裝了大量高效的方法,可以完美取代掉數組。整個容器的核心實際上就是動態分配內存,也是其性能優於數組的重要原因。下面重點解析它的核心函數push_back函數:
當數組中增加一個元素x的時候,先判斷是否還有備用空間;如果還有備用空間,則將當前指針的值設爲x,並將當前的指針加1;若備用空間已經用完,如果之前的空間爲0,則重新分配大小爲1的空間,否則將空間擴容爲之前的兩倍,然後將舊容器中的值重新拷貝到新空間中,並重新分配起始指針和當前指針。所以使用vector需要注意的一點就是儘量不要動態給它分配空間。而且空間重新分配之後,之前的所有指針都會失效(特別要注意)。
具體實現:
void push_back(const T& x) {
if (finish != end_of_storage) { //若當前還有備用空間
construct(finish, x); //將當前水位的值設爲x
++finish; //提升水位
}
else
insert_aux(end(), x);
}
template <class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
if (finish != end_of_storage) {
construct(finish, *(finish - 1));
++finish;
T x_copy = x;
copy_backward(position, finish - 2, finish - 1);
*position = x_copy;
}
else {
const size_type old_size = size(); //獲取之前數組的大小
const size_type len = old_size != 0 ? 2 * old_size : 1; //將當前數組的容量擴大爲原來的兩倍
iterator new_start = data_allocator::allocate(len); //重新分配新數組的起始迭代器
iterator new_finish = new_start;
__STL_TRY {
new_finish = uninitialized_copy(start, position, new_start); //將舊數組的值重新分配給當前的新數組
construct(new_finish, x); //將當前數組的水位的值設爲x
++new_finish; //提升新數組的水位
new_finish = uninitialized_copy(position, finish, new_finish); //這語句感覺可有可無,因爲它根本就不會執行,position即last,而finish也是last
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) { //如果重新構造的新數組出現異常,則銷燬當前新創建的數組,並釋放內存空間
destroy(new_start, new_finish);
data_allocator::deallocate(new_start, len);
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
destroy(begin(), end()); //將舊數組的空間釋放掉
deallocate();
start = new_start; //new_start記錄新數組的起始位置
finish = new_finish; //重新設置當前水位的指針
end_of_storage = new_start + len; //設置新數組的容量
}
}
[1]《STL源碼分析》----侯捷
[2]《STL3.0源碼》