list的底層:

我們之前講解了list,今天我們來看一下list的底層:

list底層是一個雙向帶頭循環的鏈表,之前我們學習數據結構的時候,我們就學過。

迭代器的封裝:

我們看這個圖片,我們的鏈表的指針可以達到鏈表的迭代器能力嗎?

達不到的,只有在數組里面,連續地數據的時候,指針才可以是看作迭代器。

迭代的兩個核心的能力就是:++和*。

在鏈表里面,數據是不連續的,對于迭代器的++,是實現不了的,得不到下一個數據的位置。*解引用的話,得到的也是這個節點,得不到里面的數據,這就和數組里面的迭代器是不一樣的。

在數組里面,數據是連續的,我們的迭代器++就可以到下一數據的個位置。*解引用就可以直接得到這個數據的。

但是:

我們在list里面我們是可以使用迭代器完成++和*的操作的,那么底層是怎么實現我們的迭代器的呢?

我們看一下我們的庫里面是怎么干的。

我們的底層使用一個自定義的類來把我們的指針封裝起來;

我們使用封裝來實現我們的迭代器的功能:

對于我們的迭代器的++和解引用*,我們可以直接使用函數重載來實現,我們直接實現在類里面。

這個類就是我們的迭代器,我們給類的名字就叫做list_iterator;

insert的底層:

我們看這個insert的底層:

我們看insert,我們的插入是把數據插入到,迭代器position位置的前面。

我們看這個代碼,我們是申請到介蒂安以后,我們的tmp的next指向position.node;

在這里可能會有疑惑,為什么是.,這個不應該是類,結構體調用里面的成員才使用的嗎?

是的:

我們在封裝我們的指針的時候,我們把我們的node結點也給封裝進去了,因為我們的后面要實現函數的重載,我們要調用node。

我們說我們的string和vector的迭代器使用的就是我們的原生指針,list使用的迭代器就是把我們的指針進行封裝,在內部實現函數重載,但是string和vector也不一定是要使用原生指針,也可以封裝他們的指針來進行。

list的底層的實現:

迭代器的實現:

我們把我們的結點的指針封裝到我們的類里面,這個類就是我們的list的迭代器。

然后我們在這個類里面,我們實現迭代器的++,*解引用等一些列的操作。

迭代器失效:

我們之前講解vector的時候,我們的insert函數和erase函數都發生了迭代器失效的問題,我們的插入函數失效的原因是我們的數組進行了擴容,但是我們的pos位置沒有進行更新,發生了迭代器失效,我們的erase函數失效的原因是我們的vs會對他進行強制的判斷,刪除數據以后這個迭代器就失效了。

這個是我們的list底層實現的insert函數,我們的list沒有擴容的問題,這里的insert是沒有迭代器失效的問題的。

這個是我們的list的刪除函數erase,這個函數和我們的vector一樣,都是會發生迭代器失效的問題的,我們的erase函數,在把pos位置的數據刪除以后,迭代器pos指向的結點就被銷毀了,這時候pos就失效了,所以我們的這個函數還是要返回下一個數據的迭代器來及時的更新我們的迭代器,來避免迭代器的失效。

這樣我們就可以向vector那樣,刪除數據以后,更新我們的迭代器;

(幾乎所有的容器的erase都會失效,至于insert會不會失效,這個就要看情況);

const修飾迭代器:

我們看這個代碼,我們在實現拷貝構造的時候,我們的參數傳的是const修飾的參數類型,這時候我們進到函數里面的話,我們使用范圍for就會報錯,因為范圍for的底層是我們的迭代器,我們的迭代器是普通的類型。

但是我們的鏈表被const修飾,我們使用迭代器對他進行遍歷的話,我們就需要const類型的迭代器來。

我們看下面的圖片:

我們的這個圖片我們看我們的上面的兩種被const修飾的指針,我們的const放在*前面的時候,我們的指針指向的數據不能被修改,但是我們的指針的指向可以修改。

當我們的const在*的右邊的時候,這時候表示我們的指針指向的數據可以被修改,但是我們的指針的指向不能被修改。

我們的const迭代器其實就是和我們的上面的第一種是一樣的,我們的迭代器指向的數據不能被修改,但是我們的迭代器的指向可以被修改;

所以,對于這種情況,我們就創建兩種迭代器來進行應對:一種普通的迭代器,再來一種const修飾的迭代器;

我們把const迭代器封裝成一個新的類,我們的const修飾的迭代器和普通的迭代器是兩個不同的類;

這個是我們的const修飾的迭代器;

這個是我們的普通的迭代器;

這兩個類的本質的卻別其實就是解引用*的實現,const修飾的迭代器我們的返回值加上const,不能讓他修改數據;

迭代器的合并:

我們實現我們的迭代器的封裝,我們封裝了兩個類,分別是我們的普通的迭代器iterator的封裝和const修飾的const_iterator的封裝,但是其實這兩個類的話,我們看了我們上面的const修飾的迭代器,其實主要的區別就是解引用函數的返回值是否是被const修飾的。

我們就可以再加一個模板參數,把我們的解引用函數的返回值換成我們的模板參數,然后我們調用我們的迭代器的時候,我們需要什么類型的迭代器,我們直接傳參就可以了。

補充:

我們看這個圖片,我們看我們對我們的vector進行初始化的狀態。

v1.push_back({ 1,1 });?等尾插操作涉及隱式類型轉換。

AA?結構體定義了帶有默認參數的構造函數?AA(int a1 = 1, int a2 = 1)?。當執行?v1.push_back({ 1,1 });?時,花括號初始化列表?{1, 1}?沒有直接對應的?AA?類型對象。此時,編譯器會利用?AA?的這個構造函數,將?{1, 1}?隱式轉換為?AA?類型臨時對象,再調用?push_back?插入到?vector<AA>?容器?v1?中 。這符合隱式類型轉換的特征,即編譯器自動利用構造函數進行類型轉換。

我們來看這個函數,我們上面使用vector容器,我們看vector里面使用了這個容器:

我們看這個,我們使用迭代器進行遍歷然后使用箭頭->解引用得到數據打印;

這個原理是什么呢?因為我們的vector的迭代器就是他的原生指針,我們的vector是一個順序表,里面的每個元素的都是AA類型的對象,我們的迭代器指向某一個位置,這個位置的數據就是一個AA對象,那么這個迭代器就是指向這個位置的指針,那么這個指針就相當于是一個結構體struct指針,我們使用指針->得到結構體里面的數據a1和a2。

我們再看,當我們的容器換成list的時候,我們還是進行遍歷打印數據,這時候我們直接->是不行的,我們的list的迭代器不是原生的指針,我們要自己封裝實現;

我們看我們實現的;這個代碼,我們返回我們的結點的數據的指針,我們的返回值是模板類型的,因為他可能是const修飾的指針,也可能不是const修飾的。

這是我們的迭代器的最后的模板;

我們繼續回到上面看:

我們的->的返回值是結點里面的數據的指針,但是這個數據是AA類型的對象,我們還要再來一個箭頭才是最終的_a1和_a2數據;? ,,但是這里是特殊的處理,省略了,方便可讀。

這個是我們實現的完整的版本:

list的底層實現/list的底層實現/list的底層實現.h · 拾億天歌/拾億天歌 - 碼云 - 開源中國

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

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

相關文章

遵循IEC62304YY/T0664:確保醫療器械軟件生命周期合規性

一、EC 62304與YY/T 0664的核心定位與關系 IEC 62304&#xff08;IEC 62304&#xff09;是國際通用的醫療器械軟件生命周期管理標準&#xff0c;適用于所有包含軟件的醫療器械&#xff08;如嵌入式軟件、獨立軟件、移動應用等&#xff09;&#xff0c;其核心目標是確保軟件的安…

【next函數python】`next()`函數

在Python中&#xff0c;next()函數結合生成器表達式用于高效地查找序列中第一個符合條件的元素。以下是如何理解和編寫類似代碼的步驟&#xff1a; 1. 生成器表達式 生成器表達式&#xff08;如 (e for e in energy3 if e ! 0)&#xff09;是一種惰性計算的迭代結構。它不會一…

[創業之路-364]:穿透表象:企業投資的深層邏輯與誤區規避

前言&#xff1a; 透過現象看本質 企業一生與人生相似 看企業如同看人 三歲看大&#xff0c;七歲看老 三十年河東&#xff0c;三十年河西 企業也有品行、文化、氣質、性格、賺錢、生命周期與賺錢曲線 投資公司的目的是未來賺錢&#xff0c;賺未來賺錢。投資創業中的企業主要看…

【C++】Stack Queue 仿函數

&#x1f4dd;前言&#xff1a; 這篇文章我們來講講STL中的stack和queue。因為前面我們已經有了string、vector和list的學習基礎&#xff0c;所以這篇文章主要關注一些stack和queue的細節問題&#xff0c;以及了解一下deque&#xff08;縫合怪&#xff09;和priority_queue &am…

[實戰] 天線陣列波束成形原理詳解與仿真實戰(完整代碼)

天線陣列波束成形原理詳解與仿真實戰 1. 引言 在無線通信、雷達和聲學系統中&#xff0c;波束成形&#xff08;Beamforming&#xff09;是一種通過調整天線陣列中各個陣元的信號相位和幅度&#xff0c;將電磁波能量集中在特定方向的技術。其核心目標是通過空間濾波增強目標方…

深圳漫云科技戶外公園實景兒童劇本殺小程序:開啟親子互動新紀元

在親子娛樂需求日益增長的當下&#xff0c;深圳漫云科技推出的戶外公園實景兒童劇本殺小程序&#xff0c;憑借其創新玩法與豐富功能&#xff0c;為親子家庭帶來全新體驗。該小程序融合戶外探險、角色扮演與邏輯推理&#xff0c;不僅滿足孩子好奇心&#xff0c;更提升其思維能力…

HOW - 如何測試 React 代碼

目錄 一、使用 React 測試庫&#xff1a;testing-library/react二、使用測試演練場&#xff1a;testing-playground.com三、使用 Cypress 或 Playwright 進行端到端測試四、使用 MSW 在測試中模擬網絡請求 一、使用 React 測試庫&#xff1a;testing-library/react testing-li…

COBOL語言的網絡安全

COBOL語言與網絡安全&#xff1a;傳統語言的新挑戰 引言 COBOL&#xff08;Common Business-Oriented Language&#xff09;是一種早期編程語言&#xff0c;最初于1959年被開發出來&#xff0c;主要用于商業、金融和行政系統的處理。盡管年代久遠&#xff0c;COBOL在大型機系…

通過世界排名第一的免費開源ERP,構建富有彈性的智能供應鏈

概述 現行供應鏈模式的結構性弱點凸顯了對整個行業進行重塑的必要性。正確策略和支持可以幫助您重塑供應鏈&#xff0c;降低成本&#xff0c;實現業務轉型。開源智造&#xff08;OSCG&#xff09;所推出的Odoo免費開源ERP解決方案&#xff0c;將供應鏈轉化為具有快速響應能力的…

Android 開發中compileSdkVersion 和 targetSdkVersion

在 Android 開發中&#xff0c;compileSdkVersion 和 targetSdkVersion 是 build.gradle 文件中的兩個關鍵配置&#xff0c;它們分別控制應用的編譯行為和運行時兼容性。以下是它們的詳細區別和用途&#xff1a; 1. compileSdkVersion&#xff08;編譯版本&#xff09; 作用&a…

Qt QComboBox 下拉復選多選

Qt 中&#xff0c;QComboBox 默認只支持單選&#xff0c;但實際使用過程中&#xff0c;我們經常會碰到需要多選的情況&#xff0c;但是通過一些直接或者曲折的方法還是可以實現的。 1、通過 QListWidget 間接實現 這種方式是網上搜索最多的一種方式&#xff0c;也是相對來說比…

Selenium自動化:玩轉瀏覽器,搞定動態頁面爬取

嘿&#xff0c;各位爬蟲愛好者和自動化達人們&#xff01;是不是經常遇到這種情況&#xff1a;信心滿滿地寫好爬蟲&#xff0c;requests一把梭&#xff0c;結果抓下來的HTML里&#xff0c;想要的數據空空如也&#xff1f;定睛一看&#xff0c;原來數據是靠JavaScript動態加載出…

天梯賽 L2-023 圖著色問題

使用vector<vector<int>> g(N)去存儲邊&#xff0c;然后每次判斷每個節點的鄰節點是不是相同的顏色&#xff0c;需要注意的是不同的顏色一定需要為K種&#xff0c;不能多也不能少。 #include<bits/stdc.h> using namespace std; int main(){int n,m,k;cin&g…

在ubuntu24上裝ubuntu22

實驗室上有一臺只裝了ubuntu24的電腦&#xff0c;但是項目要求在22上進行 搞兩個ubuntu系統&#xff01; 步驟一&#xff1a;制作22的啟動盤 步驟二&#xff1a;進入bios安裝界面 步驟三&#xff1a;選擇try or install ubuntu 步驟四&#xff1a;選擇try ubuntu 步驟五&…

【PVR Review】《Review of Deep Learning Methods for Palm Vein Recognition》

[1]譚振林,劉子良,黃藹權,等.掌靜脈識別的深度學習方法綜述[J].計算機工程與應用,2024,60(06):55-67. 文章目錄 1、Background and Motivation2、數據采集3、掌脈圖像預處理3.1、ROI提取算法3.2、圖像濾波與增強 4、掌脈識別算法4.1、基于深度學習的方法4.2、其他方法 5、融合識…

【CSP】202403-1詞頻統計

文章目錄 算法思路1. 數據結構選擇2. 輸入處理3. 統計出現的文章數4. 輸出結果 代碼示例代碼優化 樣例輸入 4 3 5 1 2 3 2 1 1 1 3 2 2 2 2 3 2樣例輸出 2 3 3 6 2 2算法思路 1. 數據結構選擇 vector<int>&#xff1a;用于存儲每篇文章的單詞列表&#xff08;可能包含…

Docker基礎1

本篇文章我將從系統的知識體系講解docker的由來和在linux中的安裝下載 隨后的文章會介紹下載鏡像、啟動新容器、登錄新容器 如需轉載&#xff0c;標記出處 docker的出現就是為了節省資本和服務器資源 當企業需要一個新的應用程序時&#xff0c;需要為它買臺全新的服務器。這樣…

Linux系統學習Day04 阻塞特性,文件狀態及文件夾查詢

知識點4【文件的阻塞特性】 文件描述符 默認為 阻塞 的 比如&#xff1a;我們讀取文件數據的時候&#xff0c;如果文件緩沖區沒有數據&#xff0c;就需要等待數據的到來&#xff0c;這就是阻塞 當然寫入的時候&#xff0c;如果發現緩沖區是滿的&#xff0c;也需要等待刷新緩…

vue 3 從零開始到掌握

vue3從零開始一篇文章帶你學習 升級vue CLI 使用命令 ## 查看vue/cli版本&#xff0c;確保vue/cli版本在4.5.0以上 vue --version ## 安裝或者升級你的vue/cli npm install -g vue/cli ## 創建 vue create vue_test ## 啟動 cd vue_test npm run servenvm管理node版本&#…

Mysql專題篇章

一、事務的四大特性&#xff1f; 1、原子性&#xff1a;是指事務包含的所有操作要么全部成功&#xff0c;要么全部失敗回滾。 2、一致性&#xff1a;是指一個事務執行之前和執行之后都必須處于一致性狀態。比如a與b賬戶共有100塊&#xff0c;兩人之間轉賬之后無論成功還是失敗…