【C++】STL——vector底層實現

目錄

💕?1.vector三個核心

💕2.begin函數,end函數的實現(簡單略講)

💕3.size函數,capacity函數的實現 (簡單略講)

💕4.reserve函數實現?(細節詳見)

💕5.resize函數實現(簡單略講,純小計算)

💕6.其他功能函數實現(略講,都是順序表那一套沒有改變)?

💕7.整體代碼實現

💕8.底層模擬測試 .cpp

💕9.完結?


一個人的堅持到底有多難?

?

?聲明:此文內容基于此文章->:【C++】STL——vector的使用

💕?1.vector三個核心

在vector中,核心成員并不是我們在數據結構實現的順序表,如size,capacity,data,而是下面三個->:

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace yz
{template<class T>class vector{typedef T* iterator;typedef const T* const_iterator;public:private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};}

我們把元素的地址T*,命名為迭代器類型,iterator

接下來分別是順序表起始位置的地址,順序表的 size 用 _finish 來表示,順序表的capacity用_end_of_storage來表示

💕2.begin函數,end函數的實現(簡單略講)

我們知道vector庫中的begin函數與end函數返回的雖然是迭代器,但是可以像指針一樣使用,因此我們可以很好的實現,如下->:

	iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}

💕3.size函數,capacity函數的實現 (簡單略講)

size函數與capacity函數的實現更是簡單,直接用指針相減即可

	size_t size(){return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}

💕4.reserve函數實現?(細節詳見)

代碼看不懂的請往下看圖片講解

	//reserve預留空間T* reserve(size_t n){size_t old_size = size();if (n > capacity()){T* tep = new T[n+1];//開辟n個空間,+1是為了單獨考慮string//將內容復制過去for (int i = 0; i < size(); i++){tep[i] = _start[i];}delete[] _start;_start = tep;_finish = _start + old_size;_end_of_storage = _start + n;tep = nullptr;}return _start;}

我們知道,capacity函數開辟的新空間只會增大,不會縮小,而開辟新空間我們需要做的第一件事就是轉移數據


這里需要先思考下如何轉移,如果用strcpy只可以轉移string類,那怎么辦?用memmove嗎?

不,memmove的復制時一個字節一個字節復制過去的,雖然復制int,double時沒有問題,但如果復制的是stirng類型,我們知道,string類的成員變量是字符串首地址,在使用memmove復制時字符串的首地址原封不動的復制了過去,這就會造成我們在釋放舊空間后,白進行了memmove的復制,這是不可取的,所以我們要用到for循環轉移數據,下面有圖->:


轉移數據思考完了,我們接著思考為什么要old_size,我們拷貝完數據后,需要轉移的就是三大核心,start,finish,和end_of_storage,那么我們將數據轉移后,釋放掉原來的舊空間,就會導致finish和end_of_storage指向的是野指針,所以我們需要保留原來的old_size,這樣才能讓finish指向正確的位置

💕5.resize函數實現(簡單略講,純小計算)

//resize預留空間
T* resize(size_t n,const T& val)
{if (n > size()){reserve(n);//先開辟出足夠的空間size_t newsize = n - size();while (newsize > 0){*(_finish++) = val;newsize--;}}return _start;
}

💕6.其他功能函數實現(略講,都是順序表那一套沒有改變)?

//判斷空
bool empty()
{if (size() == 0){return true;}
}
//尾插
void push_back(const T& x)
{if (size() == capacity()) {size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);}*_finish = x;_finish++;
}
//尾刪
void pop_back()
{empty();*_finish = 0;_finish--;
}
//指定位置插入
void insert(iterator pos, const T& val)
{assert(pos >= _start && pos <= _finish);if (size() == capacity()) {size_t count = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);pos = _start + count;}T* tep = _finish;while (tep >= pos){*(tep) = *(tep - 1);tep--;}*(pos) = val;_finish++;
}
void erase(iterator pos)
{assert(pos >= _start && pos < _finish);empty();_finish--;while (pos < _finish){*(pos) = *(pos + 1);pos++;}
}

💕7.整體代碼實現

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace yz
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}size_t size(){return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}//reserve預留空間T* reserve(size_t n){size_t old_size = size();if (n > capacity()){T* tep = new T[n+1];//開辟n個空間,+1是為了單獨考慮string//將內容復制過去for (int i = 0; i < size(); i++){tep[i] = _start[i];}delete[] _start;_start = tep;_finish = _start + old_size;_end_of_storage = _start + n;tep = nullptr;}return _start;}//resize預留空間T* resize(size_t n,const T& val){if (n > size()){reserve(n);//先開辟出足夠的空間size_t newsize = n - size();while (newsize > 0){*(_finish++) = val;newsize--;}}return _start;}//判斷空bool empty(){if (size() == 0){return true;}}//尾插void push_back(const T& x){if (size() == capacity()) {size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);}*_finish = x;_finish++;}//尾刪void pop_back(){empty();*_finish = 0;_finish--;}//指定位置插入void insert(iterator pos, const T& val){assert(pos >= _start && pos <= _finish);if (size() == capacity()) {size_t count = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);pos = _start + count;}T* tep = _finish;while (tep >= pos){*(tep) = *(tep - 1);tep--;}*(pos) = val;_finish++;}void erase(iterator pos){assert(pos >= _start && pos < _finish);empty();_finish--;while (pos < _finish){*(pos) = *(pos + 1);pos++;}}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};}

💕8.底層模擬測試 .cpp

#define _CRT_SECURE_NO_WARNINGS 
#include"vector.h"
int main()
{yz::vector<int> a1;/*a1.resize(200,3);cout<<a1.size()<<' '<<a1.capacity();a1.empty();*/a1.insert(a1.begin(), 99);a1.insert(a1.begin(), 88);a1.push_back(0);a1.push_back(20);a1.push_back(28);a1.pop_back();a1.erase(a1.begin());a1.erase(a1.end()-1);a1.resize(200, 5);a1.reserve(300);yz::vector<int> a2;if (a2.empty()){cout << "空" << endl;}for (auto e : a1){cout << e << ' ';}}

💕9.完結?

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

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

相關文章

7、怎么定義一個簡單的自動化測試框架?

定義一個簡單的自動化測試框架可以從需求理解、框架設計、核心模塊實現、測試用例編寫和集成執行等方面入手&#xff0c;以下為你詳細介紹&#xff1a; 1. 明確框架需求和范圍 確定測試類型&#xff1a;明確框架要支持的測試類型&#xff0c;如單元測試、接口測試、UI 測試等…

安卓(android)讀取手機通訊錄【Android移動開發基礎案例教程(第2版)黑馬程序員】

一、實驗目的&#xff08;如果代碼有錯漏&#xff0c;可在代碼地址查看&#xff09; 1.熟悉內容提供者(Content Provider)的概念和作用。 2.掌握內容提供者的創建和使用方法。 4.掌握內容URI的結構和用途。 二、實驗條件 1.熟悉內容提供者的工作原理。 2.掌握內容提供者訪問其…

AI取代人類?

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

C語言-----數據結構從門到精通

1.數據結構基本概念 數據結構是計算機中存儲、組織數據的方式&#xff0c;旨在提高數據的訪問和操作效率。它是實現高效算法和程序設計的基石。 目標:通過思維導圖了解數據結構的知識點,并掌握。 1.1邏輯結構 邏輯結構主要四種類型: 集合&#xff1a;結構中的數據元素之…

華為小米vivo向上,蘋果榮耀OPPO向下

日前&#xff0c;Counterpoint發布的手機銷量月度報告顯示&#xff0c;中國智能手機銷量在2024年第四季度同比下降3.2%&#xff0c;成為2024年唯一出現同比下滑的季度。而對于各大智能手機品牌來說&#xff0c;他們的市場份額和格局也在悄然發生變化。 華為逆勢向上 在2024年第…

每日一博 - 三高系統架構設計:高性能、高并發、高可用性解析

文章目錄 引言一、高性能篇1.1 高性能的核心意義1.2 影響系統性能的因素1.3 高性能優化方法論1.3.1 讀優化&#xff1a;緩存與數據庫的結合1.3.2 寫優化&#xff1a;異步化處理 1.4 高性能優化實踐1.4.1 本地緩存 vs 分布式緩存1.4.2 數據庫優化 二、高并發篇2.1 高并發的核心意…

吳恩達深度學習——有效運作神經網絡

內容來自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;僅為本人學習所用。 文章目錄 訓練集、驗證集、測試集偏差、方差正則化正則化參數為什么正則化可以減少過擬合Dropout正則化Inverted Dropout其他的正則化方法數據增廣Early stopping 歸一化梯度消失與梯度爆…

20【變量的深度理解】

一說起變量&#xff0c;懂點編程的都知道&#xff0c;但是在理解上可能還不夠深 變量就是存儲空間&#xff0c;電腦上的存儲空間有永久&#xff08;硬盤&#xff09;和臨時&#xff08;內存條&#xff09;兩種&#xff0c;永久數據重啟電腦后依舊存在&#xff0c;臨時數據只…

RESTful API的設計原則與這些原則在Java中的應用

RESTful API 是基于 REST&#xff08;Representational State Transfer&#xff09; 架構風格設計的 API&#xff0c;其核心目標是提高系統的可伸縮性、簡潔性和可維護性。以下是 RESTful API 的設計原則及在 Java 中的實現方法&#xff1a; 一、RESTful API 的核心設計原則 客…

【apt源】RK3588 平臺ubuntu20.04更換apt源

RK3588芯片使用的是aarch64架構&#xff0c;因此在Ubuntu 20.04上更換apt源時需要使用針對aarch64架構的源地址。以下是針對RK3588芯片在Ubuntu 20.04上更換apt源到清華源的正確步驟&#xff1a; 步驟一&#xff1a;打開終端 在Ubuntu 20.04中&#xff0c;按下Ctrl Alt T打…

k8s二進制集群之Kube ApiServer部署

創建kube工作目錄(僅在主節點上創建即可)同樣在我們的部署主機上創建apiserver證書請求文件根據證書文件生成apiserver證書僅接著創建TLS所需要的TOKEN創建apiserver服務的配置文件(僅在主節點上創建即可)創建apiserver服務管理配置文件對所有master節點分發證書 & TOK…

基于RK3588/RK3576+MCU STM32+AI的儲能電站電池簇管理系統設計與實現

伴隨近年來新型儲能技術的高質量規模化發展&#xff0c;儲能電站作為新能源領域的重要載體&#xff0c; 旨在配合逐步邁進智能電網時代&#xff0c;滿足電力系統能源結構與分布的創新升級&#xff0c;給予相應規模 電池管理系統的設計與實現以新的挑戰。同時&#xff0c;電子系…

K8s 分布式存儲后端(K8s Distributed Storage Backend)

K8s 分布式存儲后端 在 K8s 中實現分布式存儲后端對于管理跨集群的持久數據、確保高可用性、可擴展性和可靠性至關重要。在 K8s 環境中&#xff0c;應用程序通常被容器化并跨多個節點部署。雖然 K8s 可以有效處理無狀態應用程序&#xff0c;但有狀態應用程序需要持久存儲來維護…

FFmpeg:多媒體處理的瑞士軍刀

FFmpeg&#xff1a;多媒體處理的瑞士軍刀 前言 FFmpeg 是一個功能強大且跨平臺的開源多媒體框架&#xff0c;廣泛應用于音視頻處理領域。 它由多個庫和工具組成&#xff0c;能夠處理各種音視頻格式&#xff0c;涵蓋編碼、解碼、轉碼、流處理等多種操作。 無論是專業視頻編輯…

unordered_map/set的哈希封裝

【C筆記】unordered_map/set的哈希封裝 &#x1f525;個人主頁&#xff1a;大白的編程日記 &#x1f525;專欄&#xff1a;C筆記 文章目錄 【C筆記】unordered_map/set的哈希封裝前言一. 源碼及框架分析二.迭代器三.operator[]四.使用哈希表封裝unordered_map/set后言 前言 哈…

編程AI深度實戰:大模型哪個好? Mistral vs Qwen vs Deepseek vs Llama

?? 系列文章&#xff1a; 編程AI深度實戰&#xff1a;私有模型deep seek r1&#xff0c;必會ollama-CSDN博客 編程AI深度實戰&#xff1a;自己的AI&#xff0c;必會LangChain-CSDN博客 編程AI深度實戰&#xff1a;給vim裝上AI-CSDN博客 編程AI深度實戰&#xff1a;火的編…

neo4j-community-5.26.0 install in window10

在住處電腦重新配置一下neo4j, 1.先至官方下載 Neo4j Desktop Download | Free Graph Database Download Neo4j Deployment Center - Graph Database & Analytics 2.配置java jdk jdk 21 官網下載 Java Downloads | Oracle 中國 path: 4.查看java -version 版本 5.n…

【怎么用系列】短視頻戒除—1—對推薦算法進行干擾

如今推薦算法已經滲透到人們生活的方方面面&#xff0c;尤其是抖音等短視頻核心就是推薦算法。 【短視頻的危害】 1> 會讓人變笨&#xff0c;慢慢讓人喪失注意力與專注力 2> 讓人喪失閱讀長文的能力 3> 讓人沉浸在一個又一個快感與嗨點當中。當我們刷短視頻時&#x…

網絡原理(5)—— 數據鏈路層詳解

目錄 一. 以太網 1.1 認識以太網 1.2 網卡與以太網 1.3 以太網幀格式 二. 認識MAC地址 三. MAC地址 與 IP地址 的區別 4.1 定義 4.2 分配方式 4.3 工作層次 4.4 地址格式 4.5 尋址方式 四. ARP協議 4.1 引入 4.2 ARP的概念 4.3 ARP工作原理 五. MTU 與 MSS …

【從零開始的LeetCode-算法】922. 按奇偶排序數組 II

給定一個非負整數數組 nums&#xff0c; nums 中一半整數是 奇數 &#xff0c;一半整數是 偶數 。 對數組進行排序&#xff0c;以便當 nums[i] 為奇數時&#xff0c;i 也是 奇數 &#xff1b;當 nums[i] 為偶數時&#xff0c; i 也是 偶數 。 你可以返回 任何滿足上述條件的…