【C++初階】第11課—vector

文章目錄

  • 1. 認識vector
  • 2. vector的遍歷
  • 3. vector的構造
  • 4. vector常用的接口
  • 5. vector的容量
  • 6. vector的元素訪問
  • 7. vector的修改
  • 8. vector<vector\<int\>>的使用
  • 9. vector的使用
  • 10. 模擬實現vector
  • 11. 迭代器失效
    • 11.1 insert插入數據內部迭代器失效
    • 11.2 insert插入數據外部迭代器失效
    • 11.3 erase刪除數據迭代器失效
  • 12. 模擬實現resize
  • 13. 模擬實現vector的拷貝構造
  • 14. 模擬實現vector的賦值操作符重載
  • 15. 模擬實現reserve存在的坑
  • 16. 模擬實現vector初始化
  • 17. vector構造時容易出現的坑
  • 18. 模擬實現vector代碼

1. 認識vector

  • vector是向量、矢量的意思
  • vector其實就是數據結構階段學過的順序表,行為看起來像指針一樣的容器,底層不一定是用指針實現的,具體根據編譯器的底層實現結構為準
  • vector的使用:vector<數據類型> 對象名

在這里插入圖片描述


2. vector的遍歷

在這里插入圖片描述


3. vector的構造

在這里插入圖片描述


  • 對于vector的析構,跟string類似,它會自動調用

4. vector常用的接口

在這里插入圖片描述


  • vector上述的接口與string的接口并無二異

在這里插入圖片描述


  • cbegin( )和cend( )的用法與begin和end類似,無非就是常量迭代器不能改變數據而已

5. vector的容量

在這里插入圖片描述


在這里插入圖片描述


  • 對于判空empty和請求縮容shrink_to_fit不再過多贅述,string里面都有講到

6. vector的元素訪問

在這里插入圖片描述


在這里插入圖片描述


  • at和下標訪問操作符[ ]都是用來訪問vector內的元素,區別是越界時下標操作符[ ]會報錯,而at會拋出異常,關于這點string已經講過,后續講到捕獲異常時可重溫復習以加深理解

7. vector的修改

在這里插入圖片描述


在這里插入圖片描述


  • 其余的像swap用來交換兩個vector對象,使用時可參考官方文檔,大部分與string類模版中的用法類似

8. vector<vector<int>>的使用

  • vector<vector<int>>其實就是類似二維數組的用法,使用vector實例化出int類型的對象,再使用vector<vector<int>>實例化出vector<int>的對象

在這里插入圖片描述


在這里插入圖片描述


#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
//vector<vector<int>>的使用(楊輝三角)
size_t numRows = 0;
cin >> numRows; //行數
vector<vector<int>> vv(numRows);
//所有數設置為1
for (size_t i = 0; i < numRows; i++)
{vv[i].resize(i + 1, 1);
}
//中間元素為上面兩個元素之和
for (size_t i = 2; i < numRows; i++)
{for (size_t j = 1; j < vv[i].size() - 1; j++){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}
}
//打印
for (size_t i = 0; i < numRows; i++)
{//打印前面的空格for (size_t k = 0; k < numRows - i - 1; k++){cout << " ";}for (size_t j = 0; j < vv[i].size(); j++){cout << vv[i][j] << " ";}cout << endl;
}
return 0;
}

9. vector的使用

  • 對于vector容器,也可以使用string類型,其插入string類型的數據如下

在這里插入圖片描述


  • 關于vector和C++算法庫的一些使用,以下先作為一個了解

在這里插入圖片描述


10. 模擬實現vector

  • 之前講述過,迭代器都是左閉右開的區間,對于begin指向第一個數,而end則指向最后一個數的下個位置
  • 因此對于vector的成員變量_start和_finish、_end_of_storage來講,_finish就是指向有效數據的下個位置,_end_of_storage就指向容量的下個位置

在這里插入圖片描述


在這里插入圖片描述


  • 接下主要講reserve擴容的坑,其余較容易實現

在這里插入圖片描述


  • insert在pos位置插入字符
  • 注意:pos的類型是迭代器iterator,因為vector的成員變量是iterator類型,類似迭代器begin()和end()

在這里插入圖片描述


  • 對于上述insert插入數據的代碼,存在一個巨大隱患:迭代器失效的問題,接下來主要講容器中的迭代器失效的問題

11. 迭代器失效

11.1 insert插入數據內部迭代器失效

在這里插入圖片描述


  • 解決上面迭代器失效的方法:擴容后更新pos

在這里插入圖片描述


11.2 insert插入數據外部迭代器失效

在這里插入圖片描述


  • 即使是庫里面實現的vector,對于insert插入數據也會出現迭代器失效的問題
  • 迭代器失效的根本原因就是擴容,擴容前后外部迭代器指向的是舊空間,而擴容后舊空間被釋放,再訪問就會報錯
  • 因此對于insert插入數據后外部傳參的迭代器,由于不同的平臺結果可能不同,統一認為該迭代器失效
  • 解決辦法:insert插入數據后更新迭代器

在這里插入圖片描述


11.3 erase刪除數據迭代器失效

在這里插入圖片描述


在這里插入圖片描述


  • 解決辦法:在erase刪除數據后即使更新迭代器it

在這里插入圖片描述


  • 總結
  • 對于迭代器失效的問題,主要存在于容器插入和刪除元素時,這里以vector為例,在insert插入數據和erase刪除數據后,迭代器就處于失效的狀態,這是因為插入數據擴容導致以及刪除數據縮容導致的一系列問題
  • 對于不同的編譯器,結果可能不同,并且vs對于迭代器失效的檢查尤為嚴格,它會對失效的迭代器進行標記,如果嘗試使用這些失效的迭代器,它就會報錯
  • 因此統一認為容器插入數據和刪除數據后迭代器處于失效的狀態
  • 如果想繼續使用失效的迭代器,解決辦法就是在插入數據或刪除數據前后根據實際情況及時更新迭代器,使迭代器正確指向對應的數據

12. 模擬實現resize

在這里插入圖片描述


在這里插入圖片描述


13. 模擬實現vector的拷貝構造

在這里插入圖片描述


14. 模擬實現vector的賦值操作符重載

在這里插入圖片描述


15. 模擬實現reserve存在的坑

  • reserve擴容的第一個坑

在這里插入圖片描述


  • reserve擴容的第二個坑

在這里插入圖片描述

  • 插入前四個字符串時沒有問題,但是插入第5個字符串時,為什么會出現問題呢?
  • 因為插入第5個字符串時會擴容,reserve擴容中的memcpy其實就是一個淺拷貝,之前再C語言階段實現過memcpy這個函數,它是一個字節一個字節拷貝的
  • 參考鏈接:memcpy的使用和模擬實現

在這里插入圖片描述


在這里插入圖片描述


  • 解決方案

在這里插入圖片描述


16. 模擬實現vector初始化

  • C++11提供了vector初始化列表來進行初始化

在這里插入圖片描述


  • inltializer_list是C++11設置一個模版類型
  • 其用法和之前創建數組有點類似

在這里插入圖片描述


在這里插入圖片描述


  • C++還提供了迭代器區間初始化

在這里插入圖片描述


在這里插入圖片描述


  • 當然數組也可以當做迭代器使用

在這里插入圖片描述


17. vector構造時容易出現的坑

  • 用n個val值構造vector對象

在這里插入圖片描述


在這里插入圖片描述


  • 解決措施

在這里插入圖片描述


18. 模擬實現vector代碼

//模版
template <class T>
class vector
{
public://迭代器typedef T* iterator;typedef const T* const_iterator;//構造函數vector(){}//初始化列表初始化vector(initializer_list<T> il){reserve(il.size());for (auto& e : il){push_back(e);}cout << "初始化列表初始化:" << endl;}//迭代器區間初始化//類模板函數的成員函數,也可以是函數模版template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}//vector的構造--->n個valvector(int n, const T& val = T()){resize(n, val);}vector(size_t n, const T& val = T()){resize(n, val);}//拷貝構造 vector(const vector<T>& v){reserve(v.size());for (auto& e : v){//this->push_back(e);push_back(e);}}//有效數據sizesize_t size() const{return _finish - _start;}//容量size_t capacity() const{return _end_of_storage - _start;}//beginiterator begin(){return _start;}//enditerator end(){return _finish;}//const beginconst_iterator begin() const{return _start;}//const endconst_iterator end() const{return _finish;}//resize改變有效數據個數void resize(size_t n, const T& val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish != _start + n){*_finish = val;_finish++;}}}//擴容void reserve(size_t n){if (n > capacity()){size_t oldsize = size();T* tmp = new T[n];/*memcpy(tmp, _start, sizeof(T) * size());*/for (size_t i = 0; i < oldsize; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = oldsize + _start;_end_of_storage = n + _start;}}//尾插void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;_finish++;}//尾刪void pop_back(){assert(_finish > _start);_finish--;}//重載下標操作符[]T& operator[](size_t i){return _start[i];}//賦值操作符---第一種寫法//vector<T>& operator=(const vector<T>& v)//{//	if (this != &v)//	{//		delete[] _start;//		_start = _finish = _end_of_storage = nullptr;//		reserve(v.size());//		for (auto& e : v)//		{//			//this->push_back(e);//			push_back(e);//		}//	}//	return *this;//}void swap(vector<T> v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}//賦值操作符---第二種寫法vector<T>& operator=(const vector<T>& v){swap(v);return *this;}//任意位置插入,insert插入數據后迭代器失效void insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);//滿了擴容if (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}//挪動數據iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}//插入數據*pos = x;++_finish;}//erase刪除數據iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}//析構~vector(){delete[] _start;_start = _finish = _end_of_storage = nullptr;}
private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;
};

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

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

相關文章

【AIGC學習筆記】扣子平臺——精選有趣應用,探索無限可能

背景介紹&#xff1a; 由于近期業務發展的需求&#xff0c;我開始接觸并深入了解了扣子平臺的相關知識&#xff0c;并且通過官方教程自學了簡易PE工作流搭建的技巧。恰逢周會需要準備與工作相關的分享主題&#xff0c;而我作為一個扣子平臺的初學者&#xff0c;也想探索一下這…

mysql 學習6 DML語句,對數據庫中的表進行 增 刪 改 操作

添加數據 我們對 testdatabase 數據中 的 qqemp 這張表進行 增加數據&#xff0c;在這張表 下 打開 命令行 query console 在 軟件中就是打開命令行的意思 可以先執行 desc qqemp; 查看一下當前表的結構。 插入一條數據 到qqemp 表&#xff0c;插入時要每個字段都有值 insert…

Java Web-Request與Response

在 Java Web 開發中&#xff0c;Request 和 Response 是兩個非常重要的對象&#xff0c;用于在客戶端和服務器之間進行請求和響應的處理&#xff0c;以下是詳細介紹&#xff1a; Request&#xff08;請求對象&#xff09; Request繼承體系 在 Java Web 開發中&#xff0c;通…

李沐vscode配置+github管理+FFmpeg視頻搬運+百度API添加翻譯字幕

終端輸入nvidia-smi查看cuda版本 我的是12.5&#xff0c;在網上沒有找到12.5的torch&#xff0c;就安裝12.1的。torch&#xff0c;torchvision&#xff0c;torchaudio版本以及python版本要對應 參考&#xff1a;https://blog.csdn.net/FengHanI/article/details/135116114 創…

論文閱讀(十六):利用線性鏈條件隨機場模型檢測陣列比較基因組雜交數據的拷貝數變異

1.論文鏈接&#xff1a;Detection of Copy Number Variations from Array Comparative Genomic Hybridization Data Using Linear-chain Conditional Random Field Models 摘要&#xff1a; 拷貝數變異&#xff08;CNV&#xff09;約占人類基因組的12%。除了CNVs在癌癥發展中的…

Alibaba Spring Cloud 十三 Nacos,Gateway,Nginx 部署架構與負載均衡方案

在微服務體系中&#xff0c;Nacos 主要承擔“服務注冊與發現、配置中心”的職能&#xff0c;Gateway&#xff08;如 Spring Cloud Gateway&#xff09;通常負責“路由轉發、過濾、安全鑒權、灰度流量控制”等功能&#xff0c;而 Nginx 則常被用作“邊緣反向代理”或“統一流量入…

Next.js 實戰 (十):中間件的魅力,打造更快更安全的應用

什么是中間件&#xff1f; 在 Next.js 中&#xff0c;中間件&#xff08;Middleware&#xff09;是一種用于處理每個傳入請求的功能。它允許你在請求到達頁面之前對其進行修改或響應。 通過中間件&#xff0c;你可以實現諸如日志記錄、身份驗證、重定向、CORS配置、壓縮等任務…

ElasticSearch-文檔元數據樂觀并發控制

文章目錄 什么是文檔&#xff1f;文檔元數據文檔的部分更新Update 樂觀并發控制 最近日常工作開發過程中使用到了 ES&#xff0c;最近在檢索資料的時候翻閱到了 ES 的官方文檔&#xff0c;里面對 ES 的基礎與案例進行了通俗易懂的解釋&#xff0c;讀下來也有不少收獲&#xff0…

實驗二 數據庫的附加/分離、導入/導出與備份/還原

實驗二 數據庫的附加/分離、導入/導出與備份/還原 一、實驗目的 1、理解備份的基本概念&#xff0c;掌握各種備份數據庫的方法。 2、掌握如何從備份中還原數據庫。 3、掌握數據庫中各種數據的導入/導出。 4、掌握數據庫的附加與分離&#xff0c;理解數據庫的附加與分離的作用。…

技術中臺與終搜——2

文章目錄 5、語言處理與自動補全技術探測5.1 自定義語料庫5.1.1 語料庫映射OpenAPI5.1.2 語料庫文檔OpenAPI 5.2 產品搜索與自動補全5.2.1 漢字補全OpenAPI5.2.2 拼音補全OpenAPI 5.3 產品搜索與語言處理5.3.1 什么是語言處理&#xff08;拼寫糾錯&#xff09;5.3.2 語言處理Op…

15_業務系統基類

創建腳本 SystemRoot.cs 因為 業務系統基類的子類 會涉及資源加載服務層ResSvc.cs 和 音樂播放服務層AudioSvc.cs 所以在業務系統基類 提取引用資源加載服務層ResSvc.cs 和 音樂播放服務層AudioSvc.cs 并調用單例初始化 using UnityEngine; // 功能 : 業務系統基類 public c…

k8s優雅重啟

理論上處于terminating狀態的pod&#xff0c;k8s 就會把它從service中移除了&#xff0c;只用配置一個優雅停機時長就行了。kubectl get endpoints 驗證 因此&#xff0c;優雅重新的核心問題&#xff0c;是怎么讓空閑長連接關閉&#xff0c;再等待處理中的請求執行完。 一些底…

【Linux】華為服務器使用U盤安裝統信操作系統

目錄 一、準備工作 1.1 下載UOS官方系統 &#xff11;.&#xff12;制作啟動U盤 1.3 服務器智能管理系統iBMC 二、iBMC設置U盤啟動 一、準備工作 1.1 下載UOS官方系統 服務器CPU的架構是x86-64還是aarch64&#xff09;,地址&#xff1a;統信UOS生態社區 - 打造操作系統創…

27. 【.NET 8 實戰--孢子記賬--從單體到微服務】--簡易報表--報表服務

報表是每個記賬應用所具備的功能&#xff0c;要實現報表功能就需要把賬本的核心功能&#xff08;記賬&#xff09;完成&#xff0c;因此報表服務作為本專欄第一部分單體應用開發中最后一個要實現的功能&#xff0c;這一篇文章很簡單&#xff0c;我們一起來實現一個簡單的報表服…

基于 Node.js 的天氣查詢系統實現(附源碼)

項目概述 這是一個基于 Node.js 的全棧應用,前端使用原生 JavaScript 和 CSS,后端使用 Express 框架,通過調用第三方天氣 API 實現天氣數據的獲取和展示。 主要功能 默認顯示多個主要城市的天氣信息 支持城市天氣搜索 響應式布局設計 深色主題界面 優雅的加載動畫 技術棧 …

cursor重構谷粒商城04——vagrant技術快速部署虛擬機

前言&#xff1a;這個系列將使用最前沿的cursor作為輔助編程工具&#xff0c;來快速開發一些基礎的編程項目。目的是為了在真實項目中&#xff0c;幫助初級程序員快速進階&#xff0c;以最快的速度&#xff0c;效率&#xff0c;快速進階到中高階程序員。 本項目將基于谷粒商城…

leetcode 面試經典 150 題:簡化路徑

鏈接簡化路徑題序號71題型字符串解法棧難度中等熟練度??? 題目 給你一個字符串 path &#xff0c;表示指向某一文件或目錄的 Unix 風格 絕對路徑 &#xff08;以 ‘/’ 開頭&#xff09;&#xff0c;請你將其轉化為 更加簡潔的規范路徑。 在 Unix 風格的文件系統中規則如下…

如何在gitee/github上面搭建obsidian的圖床

在搭建圖床之前我們需要知道圖床是一個什么東西,圖床顧名思義就是存放圖片的地方&#xff0c;那么我們為什么要搭建圖床呢&#xff1f;因為我們在寫博客的時候&#xff0c;很多同學都是在本地使用typora或者是obsidian進行markdown語法的文章的書寫&#xff0c;文件格式通常都是…

JVM堆空間

JVM&#xff08;Java虛擬機&#xff09;堆空間是Java內存管理的核心區域之一&#xff0c;用于存儲Java對象實例。以下是關于JVM堆空間的詳細介紹&#xff1a; 1. 堆空間的作用 ? 存儲對象實例&#xff1a;幾乎所有的Java對象實例&#xff08;通過new關鍵字創建的對象&#xf…

Redis 的熱 Key(Hot Key)問題及解決方法

Redis 的熱 Key&#xff08;Hot Key&#xff09;問題及解決方法 1. 什么是 Redis 熱 Key&#xff1f; Redis 熱 Key&#xff08;Hot Key&#xff09;指的是訪問頻率極高的 Key&#xff0c;通常會造成以下問題&#xff1a; 單 Key 訪問量過大&#xff1a;熱點 Key 可能被高并…