C++----剖析list

前面學習了vector和string,接下來剖析stl中的list,在數據庫中學習過,list邏輯上是連續的,但是存儲中是分散的,這是與vector這種數組類型不同的地方。所以list中的元素設置為一個結構體,將list設計成雙向的:

	template <class T>struct list_node{list_node<T>* _next;list_node<T>* _pre;T _data;list_node(const T& val=T()):_next(nullptr),_pre(nullptr),_data(val){}};

接下來是stl中的迭代器部分,list的迭代器還可以像vector這種原生指針是的使用方式使用嗎?答案是否定的,因為vector的底層存儲是連續的,并且迭代器就是vector內部元素指針的簡單封裝。所以底層自然實現起來比較簡單,但是list的底層不可以,比如迭代器++,vector本來就是連續的,所以直接就能用,但是struct不是連續的,所以要自己實現,否則誰知道會++到哪里造成訪問未知空間。所以既然它不支持我們直接使用,那我們就造一個迭代器出來,這個迭代器的核心就是node:

	template <class T, class PTR, class PEF>struct _list_iterator{typedef list_node<T> Node;typedef _list_iterator<T,PTR,PEF> self;Node* _node;//核心_list_iterator(Node* node):_node(node){}PEF operator*(){return _node->_data;}//要可以返回值、還能修改!PTR operator->(){return &(operator*());}self& operator++(){_node = _node->_next;return *this;}//后置++self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_pre;return *this;}//后置--self operator--(int){self tmp(*this);_node = _node->_pre;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}};

這里其他的地方沒有太大的疑問,就是operator->發現了,返回的是nodedata的地址,首先咱們來看,當T是內置類型int時,是沒有必要用這個的吧?直接*就可以得到,但是如果T時自定義類型的呢?比如:

	struct A{int _a;int _b;A(int a = 1,int b=1):_a(a),_b(b){}};void test2(){list<A> l;l.push_back(A(1,1));l.push_back(A(2, 2));l.push_back(A(3, 3));l.push_back(A(4, 4));std::cout << it->_a << " " << it->_b << " ";list<A>::iterator it = l.begin();}

此時我想訪問A中的數據,我當然可以重載<<這個運算符了,但是在stl中我們不知道自定義類型中會有什么數據,所以stl中是不會預先,也不能寫出來<<運算符。所以就有了->符,我們可以自己訪問struct中的數據,但是還有一個問題,->返回struct的地址,還應該再來一個->吧,就是it->->_a,這里編譯器做了優化,所以只需要一個->就可以。

看list:

	template <class T>class list{typedef list_node<T> Node;public:typedef _list_iterator<T,T*,T&> iterator;typedef _list_iterator<T,const T*,const T&> const_iterator;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}list(){_head = new Node;_head->_next = _head;_head->_pre = _head;}//void push_back(Node newnode)//{//	Node* tail = _head->_pre;//	tail->_next = newnode;//	newnode->_pre = tail;//	newnode->_next = _head;//	_head->_pre = newnode;//}void push_back(const T& val){Node* newnode = new Node(val);Node* tail = _head->_pre;tail->_next = newnode;newnode->_pre = tail;newnode->_next = _head;_head->_pre = newnode;}private:Node* _head;};

list的形式:帶哨兵位的雙向列表

解釋模板在const迭代器和普通迭代器中的巧妙使用,通過模板避免多寫代碼:

?巧妙使用模板參數。

list迭代器失效的場景只存在于刪除結點時,他不像vector這種連續的,插入了會導致其中大部分元素發生移動,所以只會在刪除結點時,如何解決?返回刪除結點的下一個節點的迭代器。

附全部代碼:

	template <class T>struct list_node{list_node<T>* _next;list_node<T>* _pre;T _data;list_node(const T& val=T()):_next(nullptr),_pre(nullptr),_data(val){}};template <class T, class PTR, class PEF>struct _list_iterator{typedef list_node<T> Node;typedef _list_iterator<T,PTR,PEF> self;Node* _node;//核心_list_iterator(Node* node):_node(node){}PEF operator*(){return _node->_data;}//要可以返回值、還能修改!PTR operator->(){return &(operator*());}self& operator++(){_node = _node->_next;return *this;}//后置++self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_pre;return *this;}//后置--self operator--(int){self tmp(*this);_node = _node->_pre;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}};template <class T>class list{typedef list_node<T> Node;public:typedef _list_iterator<T,T*,T&> iterator;typedef _list_iterator<T,const T*,const T&> const_iterator;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}list(){_head = new Node;_head->_next = _head;_head->_pre = _head;}void empty_init(){_head = new Node;_head->_next = _head;_head->_pre = _head;}template<class InputIterator>list(InputIterator first, InputIterator last){empty_init();while (first != last){push_back(*first);++first;}}~list(){clear();delete _head;_head = nullptr;} void swap(list<T>& l){std::swap(_head, l._head);}list(const list<T>& l){ empty_init();list<T> tmp(l.begin(), l.end());swap(tmp);}//l2=l1 list<T>& operator=(list<T> l){swap(l);return *this;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}//void push_back(Node newnode)//{//	Node* tail = _head->_pre;//	tail->_next = newnode;//	newnode->_pre = tail;//	newnode->_next = _head;//	_head->_pre = newnode;//}void insert(iterator pos, const T& val){Node* newnode = new Node(val);Node* cur = pos._node;Node* pre = cur->_pre;cur->_pre = newnode;newnode->_next = cur;pre->_next = newnode;newnode->_pre = pre;}void push_front(const T& val){insert(begin(),val);}void push_back(const T& val){Node* newnode = new Node(val);Node* tail = _head->_pre;tail->_next = newnode;newnode->_pre = tail;newnode->_next = _head;_head->_pre = newnode;}//返回值是刪去節點的下一個節點的迭代器,避免迭代器失效,//因為釋放了當前迭代器的結點,再次訪問會出現錯誤iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* pre = cur->_pre;Node* next = cur->_next;next->_pre = pre;pre->_next = next;delete cur;return iterator(next);}void pop_front(){iterator it = erase(begin());}void pop_back(){iterator it = erase(--end());}private:Node* _head;};

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

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

相關文章

為什么已經有 Nginx 了,還需要服務網關?

在當前微服務架構中&#xff0c;雖然 Nginx 是一個高性能的反向代理和負載均衡服務器&#xff0c;但在實際使用中仍然存在諸多局限性。為了滿足運維效率、功能統一治理以及與微服務生態集成的需求&#xff0c;通常會在 Nginx 和業務服務之間引入一層基于 Java 實現的服務網關&a…

Kendo UI 中,ViewModel、DataSource 和 Grid的關系。Kendo 框架發起 HTTP 請求

Kendo UI 中&#xff0c;ViewModel、DataSource 和 Grid的關系 在 Kendo UI 中&#xff0c;ViewModel、DataSource 和 Grid 是構建動態數據應用的核心組件&#xff0c;三者協同工作實現數據的綁定、管理和展示。 一、三者關系圖解 #mermaid-svg-3lWxu2zWB23wDYEz {font-family…

宇樹開源 Qmini 雙足機器人,可通過 3D 打印動手制作,使用樹莓派作為主控制器

Unitree Qmini 是一款由宇樹科技設計并開源的低成本雙足機器人&#xff0c;開發者可以完全通過 3D 打印進行復刻。Qmini 專為業余愛好者、教育工作者和研究人員設計&#xff0c;使用戶能夠快速上手&#xff0c;并以類似樂高的模塊化方式組裝自己的機器人。該項目為機器人技術提…

解決華為云服務器無法ping通github問題

在push代碼到github上的時候&#xff0c;發現顯示22端口無法連接&#xff0c;在已經開放了端口&#xff0c;防火墻關閉的情況下仍然無法連接到GitHub。 發現是服務器和github斷連&#xff0c;選擇 sudo vim /etc/hosts 添加一下代碼 # GitHub Start140.82.121.4 gith…

關于electron-vite koffi 讀取 dll 打包等問題得記錄

koffi const koffi require(‘koffi’) import iconv from ‘iconv-lite’;const libPath path.resolve(__dirname, ‘…/…/resources/dll/sss.dll’) const yktLib koffi.load(libPath) const ret yktLib.func(‘string sss(string Url, string Data, string OutData)’…

【開發技術】.Net使用FFmpeg視頻特定幀上繪制內容

目錄 一、目的 二、解決方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg調用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 濾鏡來繪制 ROI 三、總結 一、目的 當前市場上有很多目標檢測智能識別的相關算法&#xff0c;當前調用一個醫療行業的AI識別算法后返回…

通過關鍵字批量抓取淘寶商品數據實現方法途徑分享--API

item_search 按關鍵字搜索淘寶商品item_search_tmall 按關鍵字搜索天貓商品item_search_pro 高級關鍵字搜索淘寶商品item_search_img 按圖搜索淘寶商品&#xff08;拍立淘&#xff09;item_search_shop 獲得店鋪的所有商品 一、引言 在電商領域&#xff0c;獲取淘寶商品數據對…

用 Lazarus IDE 寫一個郵件客戶端軟件,能收發郵件,編寫郵件

下面是一個使用Lazarus IDE開發的基本郵件客戶端實現方案&#xff0c;包含收發郵件和編寫郵件的核心功能。我們將使用Synapse庫&#xff08;跨平臺的網絡通信庫&#xff09;來處理郵件協議。 步驟1&#xff1a;安裝依賴 安裝Synapse庫&#xff1a; 下載地址&#xff1a;https:…

第二部分-IP及子網劃分

目錄 一、什么是IP? 1.1.IP地址的由來 1.2.IP地址的表示 1.3.IP地址的構成 1.4.IP地址的分類 1.5.IP地址類型 1.6.IP地址的計算 1.7.私網IP地址 1.8.特殊IP地址 二、子網劃分 2.1.什么是子網劃分及為什么要進行子網劃分? 2.2.如何進行子網劃分&#xff1f; 實例&#xff1a; …

【javascript】泡泡龍游戲中反彈和查找匹配算法

引言 泡泡龍游戲的核心玩法依賴于物理碰撞與顏色匹配的算法實現。反彈效果需要模擬泡泡與邊界或障礙物的彈性碰撞&#xff0c;確保軌跡符合物理規律&#xff1b;匹配算法則需快速檢測相鄰同色泡泡&#xff0c;觸發消除邏輯。高效的處理方式直接影響游戲流暢度和玩家體驗。 以…

如何使用deepseek滿血版

deepseek 訪問方式 DeepSeek滿血版可通過官方網站或官方應用商店下載安裝。確保設備滿足最低系統要求&#xff0c;如操作系統版本和硬件配置。 賬號注冊與登錄 訪問平臺后完成賬號注冊流程&#xff0c;提供必要信息并驗證郵箱或手機號。登錄后進入用戶中心&#xff0c;查看…

網絡管理【Linux/Unix/Windows】命令大全

在跨平臺網絡運維中&#xff0c;管理員常需快速切換Windows與Linux環境下的命令操作。本文整合了核心網絡管理命令的跨平臺對照表&#xff0c;涵蓋連通性測試、路由追蹤、DNS解析、ARP管理、會話監控等高頻場景。無論您負責服務器維護、網絡排障還是安全審計&#xff0c;此表可…

Gremlin創建schema(包括實體和關系)

1、構建圖譜schema&#xff0c;流程包括圖創建、實體構建以及關系構建。 創建圖時需要指定圖庫名稱以及主鍵字段。 實體構建時需要指定主鍵字段&#xff0c;每個屬性需要指定數據類型&#xff0c;是否非空以及默認值。關系構建時需要包括關系名稱、指向頭實體的標簽&#xff0c…

[論文閱讀]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代碼&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…

鴻蒙Next倉頡語言開發實戰教程:店鋪詳情頁

各位好&#xff0c;幽藍君又來分享倉頡開發教程了&#xff0c;今天的內容是店鋪詳情頁&#xff1a; 這個頁面的內容看似簡單&#xff0c;其實有很多小細節需要注意&#xff0c;主要還是讓大家熟悉List容器的使用。 整個頁面由導航欄和List容器兩大部分組成&#xff0c;導航欄我…

FEMFAT許可使用數據分析工具介紹

在高度競爭和快速變化的工程仿真領域&#xff0c;數據驅動的決策變得越來越重要。為了更好地了解FEMFAT許可的使用情況、提高資源利用率、優化工作流程&#xff0c;FEMFAT許可使用數據分析工具應運而生。本文將為您介紹這款強大的工具&#xff0c;助您輕松駕馭FEMFAT許可數據&a…

大模型原理面試題及參考答案

目錄 什么是大語言模型(LLM)?它與傳統語言模型的本質差異在哪里? 自回歸模型(autoregressive)與掩碼語言模型(masked LM)的異同是什么?各適合于哪些任務? Transformer 的核心構件——多頭自注意力機制如何捕捉長距離依賴? 位置編碼(positional encoding)的作用…

Gartner<Reference Architecture Brief: Data Integration>學習心得

數據集成參考架構解析 引言 在當今數字化時代,數據已成為企業最寶貴的資產之一。隨著企業規模的不斷擴大和業務的日益復雜,數據來源也變得多樣化,包括客戶關系管理(CRM)、企業資源規劃(ERP)、人力資源管理(HR)和市場營銷等領域的運營系統。這些系統雖然在其特定功能…

JAVASE:方法

JavaSE 方法詳解 一、方法的核心概念 方法&#xff08;Method&#xff09;是一組執行特定任務的語句集合&#xff0c;它將代碼邏輯封裝為可復用的單元&#xff0c;提高代碼的模塊化和可維護性。 方法的組成&#xff1a; [修飾符] 返回類型 方法名([參數列表]) {// 方法體[r…

MXNet-cu101 + CUDA 10.1 在 Windows 11 上啟用 GPU 的完整指南

一、報錯信息 (pytorch) C:\Users\Administrator\Desktop\test>D:/conda/anaconda3/envs/pytorch/python.exe c:/Users/Administrator/Desktop/test/test.py Traceback (most recent call last): File “c:/Users/Administrator/Desktop/test/test.py”, line 1, in import…