<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們可以通過模板實現類似vector的類。我們實現一個StrVecTemp類,其內部通過allocator開闢空間,儲存的型別用T來表示,T是模板型別。
template <typename T> class StrVecTemp { public: StrVecTemp() : elements(nullptr), first_free(nullptr), cap(nullptr) {} //拷貝建構函式 StrVecTemp(const StrVecTemp &); //拷貝賦值運運算元 StrVecTemp &operator=(const StrVecTemp &); //移動建構函式 StrVecTemp(StrVecTemp &&src) noexcept : elements(src.elements), first_free(src.first_free), cap(src.cap) { //將源資料置空 src.elements = src.first_free = src.cap = nullptr; } template <class... Args> void emplace_back(Args &&...args); //解構函式 ~StrVecTemp(); //拷貝元素 void push_back(const T &); //丟擲元素 void pop_back(T &s); //返回元素個數 size_t size() const { return first_free - elements; } //返回capacity返回容量 size_t capacity() const { return cap - elements; } //返回首元素的指標 T *begin() const { return elements; } //返回第一個空閒元素指標 T *end() const { return first_free; } private: //判斷容量不足靠皮新空間 void chk_n_alloc() { if (size() == capacity()) { reallocate(); } } //重新開闢空間 void reallocate(); // copy指定範圍的元素到新的記憶體中 std::pair<T *, T *> alloc_n_copy(const T *, const T *); //釋放空間 void free(); //陣列首元素的指標 T *elements; //指向陣列第一個空閒元素的指標 T *first_free; //指向陣列尾後位置的指標 T *cap; //初始化alloc用來分配空間 static std::allocator<T> alloc; }; template <typename T> std::allocator<T> StrVecTemp<T>::alloc;
alloc在使用前要在類外初始化,因為是模板類,所以放在.h中初始化即可。
接下來我們要實現根據迭代器開始和結束的區間copy舊元素到新的空間裡
//實現區間copy template <typename T> std::pair<T *, T *> StrVecTemp<T>::alloc_n_copy(const T *b, const T *e) { auto newdata = alloc.allocate(e - b); //用舊的資料初始化新的空間 auto first_free = uninitialized_copy(b, e, newdata); return {newdata, first_free}; }
實現copy構造
//實現拷貝建構函式 template <class T> StrVecTemp<T>::StrVecTemp(const StrVecTemp &strVec) { auto rsp = alloc_n_copy(strVec.begin(), strVec.end()); //利用pair型別更新elements, cap, first_free elements = rsp.first; first_free = rsp.second; cap = rsp.second; }
實現copy賦值
//拷貝賦值運運算元 template <class T> StrVecTemp<T> &StrVecTemp<T>::operator=(const StrVecTemp &strVec) { if (this == &strVec) { return *this; } //如果不是自賦值,就將形參copy給自己 auto rsp = alloc_n_copy(strVec.begin(), strVec.end()); elements = rsp.first; first_free = rsp.second; cap = rsp.second; }
解構函式要先銷燬資料再回收記憶體
//解構函式 template <class T> StrVecTemp<T>::~StrVecTemp() { //判斷elements是否為空 if (elements == nullptr) { return; } //快取第一個有效元素的地址 auto dest = elements; //迴圈解構 for (size_t i = 0; i < size(); i++) { //解構每一個元素 alloc.destroy(dest++); } //再回收記憶體 alloc.deallocate(elements, cap - elements); elements = nullptr; cap = nullptr; first_free = nullptr; }
重新開闢空間
template <class T> void StrVecTemp<T>::reallocate() { T *newdata = nullptr; //陣列為空的情況 if (elements == nullptr || cap == nullptr || first_free == nullptr) { newdata = alloc.allocate(1); elements = newdata; first_free = newdata; // cap指向陣列尾元素的下一個位置 cap = newdata + 1; return; } //原資料不為空,則擴充size兩倍大小 newdata = alloc.allocate(size() * 2); //新記憶體空閒位置 auto dest = newdata; //就記憶體的有效位置 auto src = elements; //通過移動操作將舊資料放到新記憶體中 for (size_t i = 0; i != size(); ++i) { alloc.construct(dest++, std::move(*src++)); } //移動完舊資料後一定要刪除 free(); //更新資料位置 elements = newdata; first_free = dest; cap = newdata + size() * 2; }
上面的函數用到了free函數,我們自己實現一個free
template <typename T> void StrVecTemp<T>::free() { //先判斷elements是否為空 if (elements == nullptr) { return; } auto dest = elements; //遍歷解構每一個物件 for (size_t i = 0; i < size(); i++) { // destroy 會解構每一個元素 alloc.destroy(dest++); } //再整體回收記憶體 alloc.deallocate(elements, cap - elements); elements = nullptr; cap = nullptr; first_free = nullptr; }
壓入元素和彈出元素
//拷貝元素 template <class T> void StrVecTemp<T>::push_back(const T &t) { chk_n_alloc(); alloc.construct(first_free++, t); } //丟擲元素 template <class T> void StrVecTemp<T>::pop_back(T &s) { //先判斷是否為空 if (first_free == nullptr) { return; } //判斷size為1 if (size() == 1) { s = *elements; alloc.destroy(elements); first_free = nullptr; elements = nullptr; return; } s = *(--first_free); alloc.destroy(first_free); }
接下來要實現emplace_back,因為emplace_back支援多種建構函式的引數,所以要用模板參數列的方式定義該函數。
模板參數列和形參列表都要用引數包的方式
template <class T> template <class... Args> void StrVecTemp<T>::emplace_back(Args &&...args) { chk_n_alloc(); alloc.construct(first_free++, forward<Args>(args)...); }
Args是模板引數包,args是參數列。因為construct的引數可能為右值參照,所以要用forward將原參數列型別原樣轉發。
// forward既擴充套件了模板引數包Args,又擴充套件了函數引數包args // std::forward<Args>(args)... 等價於std::forward<Ti>(ti) //比如傳遞給emplace_back(10,'c'); //相當於呼叫 alloc.construct(first_free++, forward<int>(10), forward<char>('c')) //呼叫的就是插入cccccccccc
本文模擬實現了vector的功能。
到此這篇關於C++模擬實現vector流程詳解的文章就介紹到這了,更多相關C++ vector內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45