跟我學C 中級篇 STL的容器vector

2021-10-19 19:29:39 字數 4590 閱讀 8172

std:vector的原始碼很容易找到,其實你看它**也不複雜,之所以看上去眼花繚亂的原因不是因為他複雜,而是為了相容和安全性搞了好多新功能和方法,再加上一些模板本身的技巧。這些都可以暫時忽略過去,重點看重點的相關的函式方法的實現。

向量的建構函式其實就是兩部分模板型別名稱和分配器,而分配器一般使用預設的分析器型別,這個回頭再分配器中再詳細分析。

template >

class vector ) 

explicit vector(const _alloc& _al) noexcept : _mypair(_one_then_variadic_args_t{}, _al) 

......

public:

vector& operator=(vector&& _right) noexcept(noexcept(_move_assign(_right, _choose_pocma<_alty>{}))) );

}return *this;

}~vector() noexcept 

......

void push_back(const _ty& _val) 

void push_back(_ty&& _val) 

template iterator emplace(const_iterator _where, _valty&&... _val)  else 

return _make_iterator(_whereptr);

}return _make_iterator(_emplace_reallocate(_whereptr, _std forward<_valty>(_val)...));

}iterator insert(const_iterator _where, const _ty& _val) 

iterator insert(const_iterator _where, _ty&& _val) 

......

void clear() noexcept 

public:

void swap(vector& _right) noexcept /* strengthened */ 

}_nodiscard _ty* data() noexcept 

_nodiscard const _ty* data() const noexcept 

_nodiscard iterator begin() noexcept 

_nodiscard const_iterator begin() const noexcept 

_nodiscard iterator end() noexcept 

_nodiscard const_iterator end() const noexcept 

_nodiscard reverse_iterator rbegin() noexcept 

_nodiscard const_reverse_iterator rbegin() const noexcept 

_nodiscard reverse_iterator rend() noexcept 

_nodiscard const_reverse_iterator rend() const noexcept 

_nodiscard const_iterator cbegin() const noexcept 

_nodiscard const_iterator cend() const noexcept 

_nodiscard const_reverse_iterator crbegin() const noexcept 

_nodiscard const_reverse_iterator crend() const noexcept 

......

}

第二級 __default_alloc_template

其實就是維護乙個記憶體池,乙個鍊錶s_free_list可以把這些空閒的記憶體連線起來,寫過記憶體池或者接觸過的一說應該就明白,其大小為16。這16個鍊錶中每個鍊錶中的空閒空間的大小都是固定的8,16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128位元組。

那麼實際分配就好說了,大於128的使用第一種,否則使用當前記憶體池中的鍊錶遍歷,查詢可用空閒找到後直接使用,否則*8,呼叫refill再次分配。

釋放相對就簡單了,同樣分成兩部分,大於128位元組轉第乙個呼叫free,否則加入**空閒列表。

template pointer _emplace_reallocate(const pointer _whereptr, _valty&&... _val) 

const size_type _newsize     = _oldsize + 1;

const size_type _newcapacity = _calculate_growth(_newsize);

const pointer _newvec           = _al.allocate(_newcapacity);

const pointer _constructed_last = _newvec + _whereoff + 1;

pointer _constructed_first      = _constructed_last;

_try_begin

_alty_traits::construct(_al, _unfancy(_newvec + _whereoff), _std forward<_valty>(_val)...);

_constructed_first = _newvec + _whereoff;

if (_whereptr == _mylast)  else 

_catch_all

_destroy(_constructed_first, _constructed_last);

_al.deallocate(_newvec, _newcapacity);

_reraise;

_catch_end

_change_array(_newvec, _newsize, _newcapacity);

return _newvec + _whereoff;

}

在c++11中提供了shrink_to_fit()函式,可以減少相關的記憶體使用,不過需要注意的,一定要看使用後是否引起了迭代器的失效,如果已經失效一定要重新處理迭代器的引用,否則會引起崩潰。

#include #include #include void testadd()

vec.resize(100);

std::cout <

vec.shrink_to_fit();

std::cout <

}void testdel()

;    std::vector::iterator it = vec.begin();

std::cout <

std::cout <

for (auto it = vec.begin(); it != vec.end(); it++)

}int main()

執行結果是:

vec size:1 vec capacity:1

vec value:1

vec value:0

vec value:2

vec value:3

vec size:100 vec capacity:100

vec size:100 vec capacity:100

first is:0end is:9

second is:1at three:3

vec content:1

vec content:2

vec content:3

vec content:4

vec content:5

vec content:6

vec content:7

vec content:8

vec content:9

vec content:

使用std::vector需要注意的有以下幾點:

1、空間的分配問題

不建議在小記憶體環境下申請使用較大的vector物件,容易引起記憶體的不足。前面提到過,如果使用預設的分配器,記憶體的處理會比實際需要的大好多,特別是做一些插入操作時,遇到臨界點會引起重新分配(大約是1.5到2倍)和拷貝,也很耗費時間。

2、自定義物件的操作符過載問題

如果使用自定義物件,因為迭代器的需要,一定在結構體或類中實現對操作符==,=及相關操作符的過載。

4、新增元素盡量使用emplace_back

原因是可以減少拷貝物件的次數。c++11提供的move語義也提供了更高效的方式。

其實寫這個stl,就很猶豫,畢竟前面有大神侯捷的stl原始碼剖析,而應用網上有官方的**,各種例程都很多並且相當清晰。但是為啥還是寫了下來呢,除了是讓中級c++篇更完善,另外乙個原因是想把更新的一些c++標準的東西揉合進來,不過限於個人的能力,可能會有不少問題,希望看到後,能及時提出來,共同進步。

跟我學C 中級篇 STL的容器Array

stl中的array陣列型別是在c tr1中才提出的,在之前只有vector這個類似於陣列的型別。但在實際應用中發現,vector和實際應用陣列還是有非常大的區別,包括迭代器訪問的控制,記憶體大小的控制等。用過vector的很容易發現它和實際使用中的陣列的諸多不同之處。換句話說,實際開發過程中,還是...

跟我學C 中級篇 STL的學習

c 的標準庫主要包含兩大類,首先是包含c的標準庫的,當然,為了適應c 對一些c庫進行了少許的修改和增加。最重要的當然是物件導向的c 庫 而c 庫又可以分成兩大類,即物件導向的c 庫和標準模板庫,也就是題目中的stl。另外在此基礎上,還要提醒同學們的是,除了上面的庫,在各個平台的開發廠商中,還會針對實...

跟我學c 中級篇 pimpl

private implementation,私有化實現。在c 中,由於語言本身的限制,沒有純粹的介面定義。這就導致了在介面的使用上很多c 的人員都是隨心而動。有用抽象類的純虛函式的,有直接用c型別的介面的。有乾脆提供介面類的 不一而足吧。根據實際情況,實事求是的選擇才是乙個好的標準。在c 中,大量...