STL原始碼剖析之vector

2021-07-08 18:09:34 字數 4777 閱讀 7609

向量vector

1.vector概述

vector的資料安排以及操作方式,與array非常相似。兩者的唯一差別在於空間的運用的靈活性。array是靜態空間,一旦配置了就不能改變;vector是動態空間,隨著元素的加入,它的內部機制會自行擴充空間以容納新元素。

vector的實現技術,關鍵在於其對大小的控制以及重新配置時的資料移動效率。一旦vector舊有空間滿載,如果客戶每新增乙個元素,vector內部只是擴充乙個元素的空間,實為不智,因為所謂擴充空間(不論多大),一如稍早說,是「配置新空間 / 資料移動 / 釋還舊空間」的大工程,時間成本很高,應該加入某種未雨綢繆的考慮。稍後我們便可以看到sgi vector的空間配置策略。

2.定義:

以下是vetor定義的源**摘錄。雖然stl規定,欲使用vector必須先包括,但sgi stl將vector實現吾更底層的

// alloc是sgi stl的空間配置器

template class vector

void fill_initialize(size_type n, const t& value)

public:

iterator begin()

iterator end()

size_type size() const

size_type capacity() const

bool empty() const

reference operator(size_type n)

vector() : start(0), finish(0), end_of_storage(0) {}

vector(size_type n, const t& value)

vector(int n, const t& value)

vector(long n, const t& value)

explicit vector(size_type n)

~vector()

destroy(start, finish); // 全域性函式

deallocate(); // 這是 vector 的乙個 member function

}reference front() // 第乙個元素

reference back() // 最後乙個元素

void push_back(const t& x)

else

insert_aux(end(), x); // 這是 vector 的乙個 member function

}void pop_back()

iterator erase(iterator position)

void resize(size_type new_size, const t& x)

void resize(size_type new_size)

void clear()

protected:

// 配置空間並填滿內容

iterator allocate_and_fill(size_type n, const t& x)

3.vector的迭代器vector維護的是乙個連續線性空間,所以不論其元素型別為何,普通指標都可以作為vector的迭代器而滿足所有必要條件,因為vector迭代器所需要的操作行為,如operator*,operator->operator++,operator--,operator+,operator-,operator+=,operator-=,普通指標天生就具備。vector支援隨機訪問,而普通指標正有著這樣的能力。所以,vector提供的是random access itrerators。

template class vector ;
根據上術定義,如果客戶端寫出這樣的**:

vector::iterator ivite;

vector::iterator svite;

ivite的型別其實就是int*,svite的類別其實就是shape*。

4.vector的資料結構

vector所採用的資料結構非常簡單:線性連續空間。它以兩個迭代器start和finish分別指向配置得來的連續空間中目前已被使用的範圍,並以迭代器end_of_storage指向整塊連續空間(含備用空間)的尾端:

template class vector ;
為了降低空間配置時的速度成本,vector實際配置的大小可能比客戶需求量更大一些,以備將來可能擴充。這便是容量(capacity)的觀念。換名話說,乙個vector的容量永遠大於或等於其大小。一旦容量等於大小,便是滿載,下次再有新增元素,整個vector就得另覓居所,見下圖。

運用start,finish,end_of_storage三個迭代器,便可輕易地提供首尾標示、大小、容量、空容器判斷、注標([ ])運運算元、最前端元素值、最後端元素值...等機能;

5.vector的構造與管理:constructor,push_back

千頭萬緒該如何說起?以客戶端 程式**為引導,觀察其所得結果並實證原**,是乙個良好的學習路徑。不面是乙個小小的測試程式,觀察重點在構造的方式、元素的新增,以及大小、容量的變化:

// filename : 4vector-test.cpp

#include #include #include using namespace std;

int main()

;

於是,data_allocator::allocatore(n)表示配置n個元素空間。

vector提供許多constructors,其中乙個允許我們指定空間大小及初值:

// 建構函式,允許指定 vector 大小 n 和初值 value

vector(size_type n, const t& value)

// 充填並予以初始化

void fill_initialize(size_type n, const t& value)

// 配置而後填充

iterator allocate_and_fill(size_type n, const t& x)

uninitialized_fill_n()會根據第一引數的型別特性(type traits)決定使用演算法fill_n()或反覆呼叫construct()來完成任務。

當我們以push_back()將元素插入於vector尾端時,該函式產生檢查是否還有備用空間,如果有就直接在備用空間上構造元素,並調整迭代器finish,使vector變大。如果沒有備用空間了,就擴大空間(重新配置、移動資料、釋放空間):

template class vector ;
於是,data_allocator::allocate(n) 表示配置n 個元素空間。

vector 提供許多 constructors,其中乙個允許我們指定空間大小及初值:

// 建構函式,允許指定 vector 大小 n 和初值 value

vector(size_type n, const t& value)

// 充填並予以初始化

void fill_initialize(size_type n, const t& value)

// 配置而後填充

iterator allocate_and_fill(size_type n, const t& x)

void push_back(const t& x)

else // 已無備用空間

insert_aux(end(), x); // vector member function,見以下列表

}template void vector::insert_aux(iterator position, const t& x)

else

catch (...)

// 析構並釋放原 vector

destroy(begin(), end());

deallocate();

// 調整迭代器,指向新vector

start = new_start;

finish = new_finish;

end_of_storage = new_start + len;

}}

注意,所謂動態增加大小,並不是在原空間之後接續新的空間(因為無法保證原空間之後尚有可供配置的空間),而是以原大小的兩倍另外配置一塊較大的空間,然後將原內容拷貝過來,然後才開始在原內容之後構造新元素,並釋放原空間。因此,對vector的任何操作,一旦引起空間重新配置,指向原vector的所有迭代器就都失效了。這是程式設計師易犯的乙個錯誤,務需小心。

stl原始碼剖析之vector

作者最近在學習c 學習侯捷的stl原始碼剖析這本書,但是我覺得裡面的內容有些古老並且生澀。比如說alloc,對於一些基礎知識不太牢固的同學不是很友好 我建議先細讀第二章前4小節,第一級分配器之後的內容可等基礎足夠再回頭彌補 雖然這本書本就不是面對像菜鳥的c 程式設計師。然一些基礎思想,程式設計方法,...

STL原始碼剖析 一 vector

開始學習 stl原始碼剖析 已經學習了前兩章 有關記憶體管理 以及 迭代器 下面 先嘗試自己寫vector再根據源 進行 修改 以下為 ifndef vector h define vector h include alloc.h define vector overflow std cerr ve...

STL原始碼剖析 容器 vector

vector 常被稱為向量容器,因為該容器擅長在尾部插入或刪除元素,在常量時間內就可以完成,時間複雜度為o 1 而對於在容器頭部或者中部插入或刪除元素,則花費時間要長一些 移動元素需要耗費時間 時間複雜度為線性階o n vector實現的關鍵在於其對大小的控制以及重新配置時的資料移動效率。vecto...