Accelerated C++ —— 簡易版std::vector類的實現
阿新 • • 發佈:2018-11-09
#include <memory> #include <iostream> #include <algorithm> namespace Ming { template<class T> class vec { public: typedef T* iterator; typedef const T* const_iterator; //typedef typename std::vector<T>::size_type size_type; typedef size_t size_type; typedef T value_type; typedef T& reference; typedef const T& const_reference; //-------------------------------------建構函式 //--重寫預設建構函式 vec() { create(); } //--帶參建構函式 //對於只帶有一個引數的建構函式,使用者只能這樣vec<int> a(100);來呼叫建構函式初始化,不能vec<int> a = 100; //即explicit 消除了隱式轉換 explicit vec(size_type n, const T& val = T()) { create(n, val); } //--複製建構函式 vec(const vec &v) { std::cout << "複製啦" << std::endl; create(v.cbegin(), v.cend()); } //--解構函式 ~vec() { uncreate(); } //--------------------------------------過載操作符號 /*宣告賦值操作符*/ vec& operator=(const vec&);//相當於vec<T>& vec<T>::operator=(const vec&); /* 返回引用,1、方面呼叫a[i]=nums;來修改值2、避免經常複製,效率高*/ T& operator[](size_type i) { return data[i]; } const T& operator[](size_type i)const { return data[i]; } //---------------------------------------迭代器(對系統指標進行改寫) iterator begin() { return data; } iterator end() { return avail; } const_iterator cbegin() const { return data; } const_iterator cend()const { return avail; } //---------------------------------------成員函式 /* 獲取動態陣列大小*/ size_type size()const { return avail - data; } void push_back(const T& val) { if (avail == limit)//空間不足,重新申請空間 grow(); unchecked_append(val);//插入新元素 } private: iterator data; iterator avail; iterator limit; std::allocator<T> alloc; void create(); void create(size_type, const_reference); void create(const_iterator, const_iterator); void uncreate(); void grow(); void unchecked_append(const_reference); }; /*賦值操作符實現*/ /* * !!當用=為一個變數提供一個初始值時,呼叫的是複製建構函式(copy constructor):直接進行賦值 * !!當用=為一個變數進行賦值時,呼叫的是operator=函式:先刪除先前的值,在進行賦值 */ template <class T> vec<T>& vec<T>::operator=(const vec<T> &rhs) { std::cout << "賦值啦" << std::endl; //****檢查是否自我賦值【若不判斷,則會導致uncreate()銷燬this本身的內容,若rhs=this,則rhs也被銷燬了】 if (&rhs != this)//this型別是vec*,指向成員函式operator=操作的物件的指標 //this繫結在左運算元上 { uncreate();//釋放左值this陣列內容 create(rhs.cbegin(), rhs.cend());//從右值複製給左值 } return *this; } template <typename T> void vec<T>::create() { data = avail = limit = nullptr; } template <typename T> void vec<T>::create(size_type n, const_reference val) { data = alloc.allocate(n);//分配n個能夠存放T的空間,並返回指向這塊空間的首元素的指標 limit = avail = data + n;//均指向末尾 std::uninitialized_fill(data, limit, val);//初始化記憶體空間 } template <typename T> void vec<T>::create(const_iterator i, const_iterator j) { data = alloc.allocate(j - i); limit = avail = std::uninitialized_copy(i, j, data);//初始化記憶體空間//返回最後一個複製賦值的下一個位置【按道理來講應該是指向空】 } template <typename T> void vec<T>::uncreate() { if (data != nullptr) { iterator it = avail; while (it != data) alloc.destroy(--it);//先自減,再用alloc銷燬it指向的記憶體塊 alloc.deallocate(data, limit - data);//**deallocate()只能傳入非空指標以及長度!!! } data = limit = avail = nullptr; } template <typename T> void vec<T>::grow() { //兩個指標相減的結果的型別為ptrdiff_t,它是一種有符號整數型別。 //減法運算的值為兩個指標在記憶體中的距離(以陣列元素的長度為單位,而非位元組), //因為減法運算的結果將除以陣列元素型別的長度。所以該結果與陣列中儲存的元素的型別無關。 size_type new_size = std::max(2 * (limit - data), static_cast<ptrdiff_t>(1)); //申請更大(2倍)的記憶體空間 //將原先內容複製到新的記憶體空間 iterator new_data = alloc.allocate(new_size); iterator new_avail = std::uninitialized_copy(data, avail, new_data); //釋放原先舊的記憶體空間 uncreate(); data = new_data; avail = new_avail; limit = new_data + new_size; } template <typename T> void vec<T>::unchecked_append(const_reference val) { alloc.construct(avail, val);//將val值複製到avail所指的記憶體塊中 ++avail; } } using namespace Ming; int main() { vec<int> temp(2, 1); temp.push_back(2); temp.push_back(3); temp.push_back(4); for (auto i = temp.begin(); i != temp.end(); ++i) std::cout << *i << std::endl; vec<int> temp1 = temp; //複製建構函式 temp = temp1; //賦值建構函式 vec<int> temp2(10); //vec<int> temp3 = 10;//只有一個引數的建構函式,有explicit則報錯,無explicit則對 }