從零開始寫STL 容器 vector

2022-07-29 03:00:14 字數 4103 閱讀 8816

vector又稱為動態陣列,那麼動態體現在**?vector和一般的陣列又有什麼區別?vector中各個函式的實現原理是怎樣的,我們怎樣使用會更高效?

在容器類的最前面我們會看到許多的typedef ,常見的如下:

public:

typedef t value_type;

typedef value_type* pointer;

typedef value_type* iterator;

typedef t& reference;

typedef size_t size_type;

typedef ptrdiff_t difference_type;

這些typedef 的意義在於:

在這裡我們只需要知道allocator類是vector類和底層記憶體之間的乙個中間層,遮蔽了記憶體分配,物件初始化的細節。

首先vector和普通陣列一樣,是在記憶體中連續分布的,然而它可以實現記憶體的動態分配(動態分配是指vector可以自動擴充自己的容量來滿足儲存元素的需要)。

現有的申請到的記憶體空間不足以滿足動態陣列增長的需求時,vector會自動申請重新分配一塊更大的記憶體(也就是會自動進行一次reserve函式,在push_back不斷插入元素的時候,為了避免大量重新分配浪費效能,會將記憶體分配到原來的兩倍)

vector內部會維護三個指標,start 指標指向vector中的第乙個元素,end指標指向vector中最後乙個元素的後面,end_of_storage 申請到記憶體的最末端。

為什麼要這樣設計?

可以在 o1 的時間 求出陣列內元素個數 和 容量(通過指標運算)

void destroyanddeallocate()

for(auto it = start; it != end; it++)

data_allocator.deallocate(start,end_of_storage-start);//由allocator**記憶體

}~vector()

void reallocate(size_type new_size = 0)

iterator new_start = data_allocator.allocate(new_size);//首先分配一塊新的記憶體

if(new_start == nullptr)

iterator new_end = ministl::uninitialized_copy(start, end, new_start);//移動元素

destroyanddeallocateall();//銷毀元素 並且 **記憶體

start = new_start;

end = new_end;

end_of_storage = start + new_size;// 設定指標位置

}

我們將從異常安全的角度來逐行分析**。

//這三行提供基本的異常安全保證

if(new_size == 0)

iterator new_start = data_allocator.allocate(new_size);//首先分配一塊新的記憶體

if(new_start == nullptr)

iterator new_end = ministl::uninitialized_copy(start, end, new_start);//may throw

destroyanddeallocateall();//析構函式 noexcept保證

//在最後替換成員指標,提供了強型別的異常安全保證

start = new_start;

end = new_end;

end_of_storage = start + new_size;// 設定指標位置

vector()

vector(size_t n, value_type val = value_type())//要求value_type 有乙個預設建構函式

vector(iterator first, iterator last)

vector(const vector&rhs)

vector(vector&&rhs)

}

value_type& operator (size_type n)

return *(start + n);

} value_type& front()

return *(start);

} value_type& back()

return *(end - 1);

}

void resize(size_type new_size, value_type val = value_type())

end = start + new_size;// 重新設定最後乙個元素位置

}else if (new_size < capacity())//小於申請到的記憶體容量

else // 重新分配記憶體

}void reserve(size_type n)

bool empty()

//modifiers

void push_back(value_type data)

void pop_back()

end--;

destroy(end);//析構

} templatevoid assign(inputiterator first, inputiterator last)

void assign(size_type n, const value_type &v)

iterator insert(iterator pos, const value_type &v)

if (size() == capacity())//記憶體申請

reallocate();

iterator new_end = end + 1;

data_allocator.construct(new_end, v);//要進行初始化否則會報錯

copy_backward(pos, end, new_end);//移動pos後面的元素到最終位置

*pos = v;//賦值

end = new_end;

end_of_storage++;

return pos;

} /*

這個函式比較複雜,一定注意end pos 的含義變化

*/iterator insert(iterator pos, const size_type &n, const value_type &val)

else //插入元素個數很多}/*

這個和上面大同小異

*/templatevoid insert(iterator pos, inputiterator first, inputiterator last)

else

}iterator erase(iterator pos)

iterator erase(iterator first, iterator last)

void clear()

void swap(vector&rhs)

bool operator==(vector& rhs)

return true;

}} bool operator!=(vector& rhs)

void operator=(const vector& rhs)

}};

templatevoid swap(vector& a, vector& b)

從零開始寫STL 模板元程式設計之tuple

class template std tuple is a fixed size collection of heterogeneous values.it is a generalization of std pair.可以用來在bind中儲存函式指標和引數 不定引數模板 模板偏特化 tuple作...

從零開始寫STL 二叉搜尋樹

二叉查詢樹 binary search tree 又 二叉搜尋樹,二叉排序樹 它或者是一棵空樹,或者是具有下列性質的二叉樹 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值 它的左 右子樹也分別為二叉排序樹。平均情況下插入查詢...

如何從零開始寫shell指令碼

如何從零開始寫shell指令碼 一 前言 為什麼我們需要使用shell 指令碼?難道我們之前學習的c c 不能夠完成shell指令碼語言的功能嗎,為什麼我們還需要學習shell指令碼?學習shell指令碼最大的好處是能夠輕易處理檔案與目錄之類的物件,如果同樣此類任務,利用c 或者c,則編寫程式很麻煩...