【vector模擬實現】附加代碼講解

vector模擬實現

  • 一、看源代碼
  • 簡單實現
    • 1. push_back
      • capacity(容量)
      • size
      • reserve(擴容)
      • operator[ ] (元素訪問)
    • 2. pop_back
    • 3. itorator(迭代器)
    • 4.insert & erase (頭插頭刪)
    • 5. 拷貝構造和析構函數
      • default關鍵字(強制編譯器生成)
    • 其他問題

一、看源代碼

  • 在我們自己實現 vector 的時候,我們可以參考 vector 的源代碼

在這里插入圖片描述

  • 大致功能初步了解
    1. 成員變量
    1. 核心成員函數
  • 根據名字連蒙帶猜,通過時間看源碼細節確認

我們自定義的成員變量:

template<class T>
class vector
{
public:private:T* _a;size_t _size;size_t _capacity;
};

修改后:

namespace bit  //同一個域內,就不會和編譯器里面的vector弄混
{template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;};
}

簡單實現

前情提要:我們分離定義不分離是因為分離會出現連接問題,這個我們后面會提到

1. push_back

在這里插入圖片描述

下面是push-back的大致框架:

void push_back(const T& x)
{//如果滿了就擴容if(_finish == _end_of_storage){//擴容}
}

注意:在這里我們還要實現三個前提函數:capacity()、size()、reserve()

capacity(容量)

size_t capacity()
{return _end_of_storage - _start;
}

size

size_t size()
{return _finish - _start;
}

reserve(擴容)

void reserve(size_t n)
{//直接擴容if (n > capacity()){T* tmp = new T[n];  //開辟空間memcpy(tmp, _start, sizeof(T) * size());  //拷貝delete[] _start; //釋放舊空間_start = tmp;  //指向新空間}_finish = _start + size();_end_of_storage = _start + n;
}

?通過以上代碼,我們就可以開始實現👇

void push_back(const T& x)
{//如果滿了就擴容if (_finish == _end_of_storage){//如果capacity 是 0 那么就給四個空間,不是就乘二倍size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = x;++_finish;
}

在這里插入圖片描述

operator[ ] (元素訪問)

T& operator[](size_t i)
{assert(i < size());//斷言檢查越界情況return _start[i];
}

問題一:測試會發現,我們沒有包iostream頭文件,所以cout無法使用
在這里插入圖片描述

  • 這里就涉及到一個問題 頭文件 .h.cpp 文件里面會展開

所以當我們在Test.cpp里面展開vector.h時,又可以使用了
在這里插入圖片描述

  • 因為展開時他會向上查找
    在這里插入圖片描述
    在這里插入圖片描述

但但但是,又有一個問題,運行報錯了在這里插入圖片描述

在這里插入圖片描述

  • 空指針問題,通過測試,我們可以發現的是,size算法出現問題

start 是新的 但是 finish 是舊的

當我們重新擴容之后,_start == tmp , 而_ finish還是原來的那個t

在這里插入圖片描述

  • 修改后代碼如下:
void reserve(size_t n)
{//直接擴容if (n > capacity()){size_t oldsize = size();T* tmp = new T[n];  //開辟空間if (_start) {memcpy(tmp, _start, sizeof(T) * size());  //拷貝delete[] _start; //釋放舊空間	}_start = tmp;  //指向新空間_finish = tmp + oldsize;_end_of_storage = _start + n;}}

2. pop_back

那么這個就比較簡單了,代碼實現如下👇:

void pop_back()
{assert(size() > 0);--_finish
}

3. itorator(迭代器)

  • 在沒有迭代器的情況下時,我們是不能使用范圍for的
    在這里插入圖片描述
    迭代器代碼實現👇
typedef T* iterator;
iterator begin()
{return _start;
}
iterator end()
{return _finish;
}

在這里插入圖片描述

  • 當然,也有const迭代器
    是指迭代器指向的內容不可修改
typedef const T* const_iterator;iterator begin() const
{return _start;
}
iterator end() const
{return _finish;
}

4.insert & erase (頭插頭刪)

在這里插入圖片描述

void test_vector3()
{bit::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.insert(v1.begin(), 0); //頭插v1.erase(v1.begin());  //頭刪
}

運行結果:
在這里插入圖片描述
?insert的的實現

void insert(iterator pos, const T& x)
{if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;
}

注意:這里的擴容會導致迭代器失效,本質上也是一種野指針,pos指向的位置已經失效了

在這里插入圖片描述

  • 所以我們只需要將pos指向新空間對應的位置就好
    在這里插入圖片描述
    修改后的insert👇
void insert(iterator pos, const T& x)
{if (_finish == _end_of_storage){size_t len = pos - _start;  //加上這一句計算pos的位置size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len; //重置為新pos的位置}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;
}
  • 緊接而來的問題,當我們調用自己寫insert時,pos會失效,使得在后面不能重新在調用pos
insert(pos,100);

erase的實現代碼👇

void erase(iterator pos)
{assert(pos >= _start);assert(pos <= _finish);iterator it = pos + 1;while (it != _finish){*(it - 1) = *it;**it;}--_finish;
}
  • 當我們使用erase但是也會出現失效的可能性,這也說明迭代器失效不只是野指針的問題

在這里插入圖片描述

  • 這取決于VS的編譯器對于iterator,我們出了作用域時,會類似標記為 false ,此時再次調用,就會報錯
    在這里插入圖片描述

5. 拷貝構造和析構函數

  • 拷貝構造
    問題一:如果我們不寫拷貝構造的話,在VS里面默認是什么
    在內置類型里面,我們完成的是值拷貝,也就是所謂的淺拷貝,這不是我們所需要的

在這里插入圖片描述
在這里插入圖片描述

拷貝構造函數代碼如下👇

void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}// v1 = v3
vector<T>& operator=(vector<T>& v)
{this->swap(v);return *this;
}
//v2(v1)
vector(const vector<T>& v)
{for (auto e : v){push_back(e);}
}//但是現在并沒有寫構造
  • 但是在這里并沒有運行,所以在這里我們需要提前了解一下關鍵字

default關鍵字(強制編譯器生成)

//強制編譯器生成默認的
vector() = dafault;

析構函數代碼如下👇

~vector()
{if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}
}

其他問題

  • 有人在編譯的時候可能會出現內部編譯器出錯
  • 因為有模板的原因,編譯器報錯比較混亂
  • 一般都是少了分號的原因
  • 可以用分段注釋的方法來解決

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/24138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/24138.shtml
英文地址,請注明出處:http://en.pswp.cn/web/24138.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

哈夫曼樹的創建

要了解哈夫曼樹&#xff0c;可以先了解一下哈夫曼編碼&#xff0c;假設我們有幾個字母&#xff0c;他們的出現頻率是A: 1 B: 2 C: 3 D: 4 E: 5 F: 6 G: 7。那么如果想要壓縮數據的同時讓訪問更加快捷&#xff0c;就要讓頻率高的字母離根節點比較進&#xff0c;容易訪問&#xf…

立創·天空星開發板-GD32F407VE-GPIO

本文以 立創天空星開發板-GD32F407VET6-青春版 作為學習的板子&#xff0c;記錄學習筆記。 立創天空星開發板-GD32F407VE-GPIO 基礎概念三極管MOS管 GPIO輸出模式輸出線與GPIO輸入模式GPIO點燈 基礎概念 GPIO&#xff0c;全稱為“通用輸入/輸出”&#xff08;General Purpose …

算法金 | 這次終于能把張量(Tensor)搞清楚了!

大俠幸會&#xff0c;在下全網同名[算法金] 0 基礎轉 AI 上岸&#xff0c;多個算法賽 Top [日更萬日&#xff0c;讓更多人享受智能樂趣] 1. 張量&#xff08;Tensor&#xff09;基礎概念 1.1 張量的定義與重要性 張量是深度學習中用于表示數據的核心結構&#xff0c;它可以視…

《帝國時代 III:決定版》秘籍 怎么在蘋果電腦上玩《帝國時代 III:決定版》

《帝國時代 III&#xff1a;決定版》是一款讓玩家沉浸于歷史長河體驗從大航海時代到工業革命時期的游戲。下面我們來看看《帝國時代 III&#xff1a;決定版》是什么類型的游戲&#xff0c;《帝國時代 III&#xff1a;決定版》Mac安裝教程的相關內容。 一、《帝國時代 III&…

【BOM02】本地存儲

一&#xff1a;什么是本地存儲 數據存儲在用戶瀏覽器中&#xff0c;用戶設置、讀取方便&#xff0c;同時頁面刷新時不會丟失數據。存儲在瀏覽器中數據約5M&#xff0c;分為sessionStorage和localStorage兩種存儲方式 二&#xff1a;localStorage存儲 作用 將數據永久存儲在…

opencv實戰小結-銀行卡號識別

實戰1-銀行卡號識別 項目來源&#xff1a;opencv入門 項目目的&#xff1a;識別傳入的銀行卡照片中的卡號 難點&#xff1a;銀行卡上會有一些干擾項&#xff0c;如何排除這些干擾項&#xff0c;并且打印正確的號碼是一個問題 最終效果如上圖 實現這樣的功能需要以下幾個步驟…

基于Amazon Linux使用pip安裝certbot并使用Apache配置證書的完整步驟

配置證書 1. 更新系統和安裝必要的軟件包 首先&#xff0c;確保系統和包管理器是最新的&#xff1a; sudo dnf update -y sudo dnf install -y python3 python3-pip python3-virtualenv httpd mod_ssl2. 創建并激活虛擬環境 為了避免依賴沖突&#xff0c;使用virtualenv創建…

算法導論實戰(三)(算法導論習題第二十四章)

&#x1f308; 個人主頁&#xff1a;十二月的貓-CSDN博客 &#x1f525; 系列專欄&#xff1a; &#x1f3c0;算法啟示錄 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻擋不了春天的腳步&#xff0c;十二點的黑夜遮蔽不住黎明的曙光 目錄 前言 第二十四章 24.1-3 24.1-4 2…

筆記:DST與HPPC測試方法

一、DST測試方法&#xff1a; DST全稱為Dynamic Stress Test,是一種動態壓力測試方法&#xff0c;主要用于評估電池在實際使用條件下的綜合性能&#xff0c;模擬了車輛在行駛過程中可能會遇到的各種動態負載變化&#xff0c;如加速、減速、怠速等工況。 它的目的是評估電池在…

setattr前端接收方法深度解析

setattr前端接收方法深度解析 在前端開發中&#xff0c;setattr可能是一個較為陌生的概念&#xff0c;但它卻在某些場景下扮演著關鍵角色。setattr是一個Python內置函數&#xff0c;用于設置對象屬性的值。然而&#xff0c;在前端與后端交互的過程中&#xff0c;我們有時需要處…

【Week-R2】使用LSTM實現火災預測(tf版本)

【Week-R2】使用LSTM實現火災預測&#xff08;tf版本&#xff09; 一、 前期準備1.1 設置GPU1.2 導入數據1.3 數據可視化 二、數據預處理(構建數據集)2.1 設置x、y2.2 歸一化2.3 劃分數據集 三、模型創建、編譯、訓練、得到訓練結果3.1 構建模型3.2 編譯模型3.3 訓練模型3.4 模…

超詳細的java Comparable,Comparator接口解析

前言 Hello大家好呀&#xff0c;在java中我們常常涉及到對象的比較&#xff0c;不同于基本數據類型&#xff0c;對于我們的自定義對象&#xff0c;需要我們自己去建立比較標準&#xff0c;例如我們自定義一個People類&#xff0c;這個類有name和age兩個屬性&#xff0c;那么問…

[數據集][圖像分類]蘑菇分類數據集3122張215類別

數據集類型&#xff1a;圖像分類用&#xff0c;不可用于目標檢測無標注文件 數據集格式&#xff1a;僅僅包含jpg圖片&#xff0c;每個類別文件夾下面存放著對應圖片 圖片數量(jpg文件個數)&#xff1a;3122 分類類別數&#xff1a;215 類別名稱:[“almond_mushroom”,“amanita…

實驗筆記之——DPVO(Deep Patch Visual Odometry)

本博文記錄本文測試DPVO的過程&#xff0c;本博文僅供本人學習記錄用~ 《Deep Patch Visual Odometry》 代碼鏈接&#xff1a;GitHub - princeton-vl/DPVO: Deep Patch Visual Odometry 目錄 配置過程 測試記錄 參考資料 配置過程 首先下載代碼以及創建conda環境 git clo…

Data Management Controls

Data Browsing and Analysis Data Grid 以標準表格或其他視圖格式&#xff08;例如&#xff0c;帶狀網格、卡片、瓷磚&#xff09;顯示數據。Vertical Grid 以表格形式顯示數據&#xff0c;數據字段顯示為行&#xff0c;記錄顯示為列。Pivot Grid 模擬微軟Excel的樞軸表功…

有待挖掘的金礦:大模型的幻覺之境

人工智能正在迅速變得無處不在&#xff0c;在科學和學術研究中&#xff0c;自回歸的大型語言模型&#xff08;LLM&#xff09;走在了前列。自從LLM的概念被整合到自然語言處理&#xff08;NLP&#xff09;的討論中以來&#xff0c;LLM中的幻覺現象一直被廣泛視為一個顯著的社會…

Oracle EBS AP發票創建會計科目提示:APP-SQLAP-10710:無法聯機創建會計分錄

系統版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 問題癥狀: 提交“創建會計科目”請求提示錯誤信息如下: APP-SQLAP-10710:無法聯機創建會計分錄。 請提交應付款管理系統會計流程,而不要為此事務處理創建會計分錄解決方法 數據修復SQL腳本: UPDATE ap_invoi…

LabVIEW閥性能試驗臺測控系統

本項目開發的閥性能試驗臺測控系統是為滿足國家和企業相關標準而設計的&#xff0c;主要用于汽車氣壓制動系統控制裝置和調節裝置等產品的綜合性能測試。系統采用工控機控制&#xff0c;配置電器控制柜&#xff0c;實現運動控制、開關量控制及傳感器信號采集&#xff0c;具備數…

vue封裝一個查詢URL參數方法

vue封裝一個查詢URL參數方法 在 Vue 中&#xff0c;你可以封裝一個查詢 URL 參數的方法來獲取 URL 中的查詢參數。以下是一個示例代碼&#xff1a; export const getQueryParam (param) > {const urlParams new URLSearchParams(window.location.search);return urlPara…

算法-分治策略

概念 分治算法&#xff08;Divide and Conquer&#xff09;是一種解決問題的策略&#xff0c;它將一個問題分解成若干個規模較小的相同問題&#xff0c;然后遞歸地解決這些子問題&#xff0c;最后合并子問題的解得到原問題的解。分治算法的基本思想是將復雜問題分解成若干個較…