38 C++ STL模板庫7-迭代器

C++ STL模板庫7-迭代器

文章目錄

  • C++ STL模板庫7-迭代器
    • 一、迭代器的核心作用
    • 二、迭代器的五大分類與操作
    • 三、關鍵用法與代碼示例
      • 1. 迭代器的原理
      • 2. 迭代器用法與示例
      • 3. 迭代工具用法示例
      • 4. 使用技巧

迭代器是C++中連接容器與算法的通用接口,提供了一種訪問容器元素的統一方式,類似于指針但更強大。
使用迭代器需包含 <iterator>

一、迭代器的核心作用

  1. 解耦容器與算法

    • 算法(如 std::sort, std::copy)通過迭代器操作容器,無需知道容器具體類型(數組、鏈表等)。
    • 示例:std::sort(vec.begin(), vec.end()) 可對 vectordeque 等均生效。
  2. 統一訪問模式

    • 無論容器如何存儲數據(連續內存/鏈表/樹),迭代器提供一致的遍歷接口(++, *, ->)。
  3. 支持范圍操作

    • 通過 begin()end() 定義半開區間 [begin, end),安全遍歷且避免越界。

二、迭代器的五大分類與操作

  1. 根據功能由弱到強分為:

    分類支持操作典型容器
    輸入迭代器只讀一次(*it, ++, ==istream_iterator
    輸出迭代器只寫一次(*it=, ++ostream_iterator
    前向迭代器多次讀寫(++forward_list, 哈希表
    雙向迭代器雙向移動(++, --list, set, map
    隨機訪問迭代器跳躍訪問(+n, -n, [], 比較)vector, deque, 數組
  2. 核心聲明語法

    容器類型::iterator 變量名;         // 可修改元素的迭代器  
    容器類型::const_iterator 變量名;   // 只讀元素的迭代器  
    容器類型::reverse_iterator 變量名; // 反向迭代器  
    
    vector<int>::iterator it = vn.begin ();
    array<int,5>::iterator it = vn.begin ();
    array<string>::iterator it = vn.begin ();
    

    下面的語句令一個整型向量的迭代器指向該向量的第一個元素:
    it = vn.begin ();
    而下面的語句令該迭代器指向向量中最后一個元素的下一個位置:
    it = vn.end ();
    通過begin()和end()構建迭代循環:

    for (vector<int>::iterator it = vn.begin(); it != vn.end (); it++)...
    一般用 auto 類型推導代替 vector<int>::iterator ,來縮短代碼和防止出錯
    

    遍歷容器中元素。
    迭代器的基本操作:*、++/–、+/-/+=/-=整數(部分容器的迭代器)

  3. 迭代器工具函數(需包含 <iterator>

    函數語法/示例作用
    std::advanceadvance(iter, n)移動迭代器n步(支持正負方向)
    std::distancedistance(iter1, iter2)計算兩個迭代器之間的元素數量
    std::next/std::prevnext(iter, n=1)prev(iter, n=1)獲取移動后的迭代器副本(不修改原迭代器)

    示例:

    std::deque<int> dq = {10, 20, 30};  
    auto dq_it = dq.begin();  
    std::advance(dq_it, 2);      // 移動到第3個元素(30)  
    auto count = std::distance(dq.begin(), dq.end()); // 計算長度(3)  
    auto next_it = std::next(dq_it, -1); // 獲取前一個位置的迭代器(20)  
    

三、關鍵用法與代碼示例

1. 迭代器的原理

迭代器本質是抽象化的指針
迭代器模式的核心價值在于解耦數據結構和算法

int arr[5] = {10, 20, 30, 40, 50};  // ? 指針作為迭代器的用法  
int* begin = arr;      // 首元素迭代器  
int* end = arr + 5;    // 尾后迭代器  // 遍歷操作  
for (int* it = begin; it != end; ++it) {  std::cout << *it << " ";  // 輸出:10 20 30 40 50  
}  // 隨機訪問  
*(begin + 2) = 99;    // 修改第三個元素 → arr[2]=99  
std::cout << begin[3]; // 輸出:40(等價于*(begin+3))  // 算法應用  
auto min_pos = begin;  
for (int* p = begin + 1; p != end; ++p) {  if (*p < *min_pos) min_pos = p;  
}  
std::cout << "最小值:" << *min_pos; // 輸出:10    
  • 指針迭代的缺點:
    1. 無邊界檢查:end + 1 會導致未定義行為
    2. 無類型封裝:無法區分 int* 是迭代器還是普通指針
    3. 功能缺失:不支持反向迭代器等高級特性

2. 迭代器用法與示例

  1. 遍歷數組(正/反向)

    #include <iostream>  
    #include <array>  int main() {  std::array<int, 4> arr = {10, 20, 30, 40};  // 正向迭代器(常量與非常量)  for(auto it = arr.begin(); it != arr.end(); ++it) {  *it += 1;  // 修改元素值  std::cout << *it << " ";  // 輸出:11 21 31 41  }  // 反向迭代器(C++11)  for(auto rit = arr.rbegin(); rit != arr.rend(); ++rit) {  std::cout << *rit << " ";  // 輸出:41 31 21 11  }  
    }  
    
  2. 遍歷容器

    std::array<int, 3> arr = {10, 20, 30};  for (std::array<int, 3>::iterator it = arr.begin();  it != arr.end();  ++it) {  std::cout << *it << " "; // 輸出:10 20 30  
    }  auto it = arr.begin() + 2;  
    *it = 99;                //  // C++11范圍for(底層使用迭代器)  
    for (int val : arr) {  std::cout << val << " ";  //輸出:10 20 99  
    }   
    
  3. 與標準算法結合

    #include <iostream>  
    #include <array>  
    #include <algorithm>  
    #include <numeric>  //  accumulate? 必須包含此頭文件  int main() {  std::array<int, 4> arr = {10, 20, 30, 40};  // 正向迭代器(常量與非常量)//std::array<int, 4>::iterator it for(auto it = arr.begin();  it != arr.end();  ++it) {  *it += 1;  // 修改元素值  std::cout << *it << " ";  // 輸出:11 21 31 41  }  // 反向迭代器(C++11)  for(auto rit = arr.rbegin();  rit != arr.rend();  ++rit) {  std::cout << *rit << " ";  // 輸出:41 31 21 11  }  std::sort(arr.begin(), arr.end());  // 查找元素  auto pos = std::find(arr.cbegin(), arr.cend(), 21);  if(pos != arr.end()) {  std::cout << "位置索引:" << pos - arr.begin()<<std::endl;  // 輸出:1  }  // 累加計算(C++17)  int sum = std::accumulate(arr.cbegin(),  arr.cend(), 0);std::cout << "總和:" << sum<<std::endl;  // 輸出:104 
    }
    
  4. 隨機訪問操作

    auto first = arr.begin();  
    auto third = first + 2;  // 直接跳轉到索引2  std::cout << *(first + 1) <<std::endl;    // 輸出:21(等價于arr[1])  
    std::cout << (third > first) <<std::endl; // 輸出:1(支持比較)  
    std::cout << third[1] <<std::endl;        // 輸出:41(索引相對訪問)  
    
  5. 安全訪問:常量迭代器

    void printArray(const std::array<int, 4>& arr) 
    {  // 使用cbegin/cend防止意外修改  for(auto it = arr.cbegin(); it != arr.cend(); ++it) {  std::cout << *it << " ";  // *it = 0;  // 錯誤!常量迭代器禁止修改  }  
    }
    

3. 迭代工具用法示例

  1. 基礎迭代器操作工具

    1. std::next / std::prev(安全位移)

      #include <iterator>
      std::vector<int> vec{10, 20, 30, 40};// 向前移動2步(支持所有迭代器類型)
      auto it_next = std::next(vec.begin(), 2); // 指向30 // 向后移動1步(僅雙向迭代器可用)
      auto it_prev = std::prev(vec.end(), 1);   // 指向40 
      
    2. std::advance(原位修改迭代器)

      auto it = vec.begin();
      std::advance(it, 3);  // it直接指向40(無返回值,修改原迭代器)
      

      特性對比:

      • std::next的區別:直接修改迭代器,適用于循環中逐步推進。
    3. std::distance(計算距離)

      int len = std::distance(vec.begin(), vec.end()); // 輸出4(元素總數)
      

      兼容性:

      • 隨機訪問迭代器:O(1) 時間復雜度
      • 其他迭代器:O(n) 時間復雜度(需遍歷)

4. 使用技巧

  • 迭代器的顯式聲明和類型推導

    • 顯式聲明
      std::array<int, 4>::iterator it;
    • 類型推導
      auto it;
  • 獲取首尾元素的迭代器

    auto front_it = arr.begin();      // 首元素迭代器  
    auto back_it  = arr.end() - 1;     // 尾元素迭代器(因end()指向末尾后一位)  
    
  • 數組與指針互操作

    int* ptr = arr.data();           // 獲取原生指針  
    auto it_from_ptr = arr.begin() + (ptr - arr.data()); // 指針轉迭代器  
    
  • 優先使用范圍for循環

    for (int val : arr) { ... }  // 簡潔安全  
    
  • 只讀訪問用cbegin/cend

    auto it = arr.cbegin();  // 明確表達只讀意圖  
    
  • 隨機訪問時檢查邊界

    if(index < arr.size()) {  auto it = arr.begin() + index;  
    }  
    

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

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

相關文章

【0基礎3ds Max】學習計劃

3ds Max 作為一款功能強大的專業 3D 計算機圖形軟件&#xff0c;在影視動畫、游戲開發、建筑可視化、產品設計和工業設計等眾多領域有著廣泛的應用。 目錄前言一、第一階段&#xff1a;基礎認知&#xff08;第 1 - 2 周&#xff09;?二、第二階段&#xff1a;建模技術學習&…

用 Enigma Virtual Box 將 Qt 程序打包成單 exe

上一篇介紹了用windeployqt生成可運行的多文件程序,但一堆文件分發起來不夠方便。有沒有辦法將所有文件合并成一個 exe? 答案是肯定的 用Enigma Virtual Box工具就能實現。本文就來講解如何用它將 Qt 多文件程序打包為單一 exe,讓分發更輕松。 其中的 一定要選 第二個 一…

【LeetCode 熱題 100】45. 跳躍游戲 II

Problem: 45. 跳躍游戲 II 給定一個長度為 n 的 0 索引整數數組 nums。初始位置為 nums[0]。 每個元素 nums[i] 表示從索引 i 向后跳轉的最大長度。換句話說&#xff0c;如果你在索引 i 處&#xff0c;你可以跳轉到任意 (i j) 處&#xff1a; 0 < j < nums[i] 且 i j &…

池式管理之線程池

1.初識線程池問&#xff1a;線程池是什么&#xff1f;答&#xff1a;維持管理一定數量的線程的池式結構。&#xff08;維持&#xff1a;線程復用 。 管理&#xff1a;沒有收到任務的線程處于阻塞休眠狀態不參與cpu調度 。一定數量&#xff1a;數量太多的線程會給操作系統帶來線…

嬰兒 3D 安睡系統專利拆解:搭扣與智能系帶的鎖定機制及松緊調節原理

凌晨2點&#xff0c;你盯著嬰兒床里的小肉團直嘆氣。剛用襁褓裹成小粽子才哄睡的寶寶&#xff0c;才半小時就蹬開了裹布&#xff0c;小胳膊支棱得像只小考拉&#xff1b;你手忙腳亂想重新裹緊&#xff0c;結果越裹越松&#xff0c;裹布滑到脖子邊&#xff0c;寶寶突然一個翻身&…

pandas中df.to _dict(orient=‘records‘)方法的作用和場景說明

df.to _dict(orientrecords) 是 Pandas DataFrame 的一個方法&#xff0c;用于將數據轉換為字典列表格式。以下是詳細解釋及實例說明&#xff1a; 一、核心含義作用 將 DataFrame 的每一行轉換為一個字典&#xff0c;所有字典組成一個列表。 每個字典的鍵&#xff08;key&#…

阿里云Anolis OS 8.6的公有云倉庫源配置步驟

文章目錄一、備份現有倉庫配置&#xff08;防止誤操作&#xff09;二、配置阿里云鏡像源2.1 修改 BaseOS 倉庫2.2 修改 AppStream 倉庫三、清理并重建緩存四、驗證配置4.1 ?檢查倉庫狀態?&#xff1a;五、常見問題解決5.1 ?HTTP 404 錯誤5.2 ?網絡連接問題附&#xff1a;其…

回歸預測 | Matlab實現CNN-BiLSTM-self-Attention多變量回歸預測

回歸預測 | Matlab實現CNN-BiLSTM-self-Attention多變量回歸預測 目錄回歸預測 | Matlab實現CNN-BiLSTM-self-Attention多變量回歸預測預測效果基本介紹程序設計參考資料預測效果 基本介紹 1.Matlab實現CNN-BiLSTM融合自注意力機制多變量回歸預測&#xff0c;CNN-BiLSTM-self-…

103、【OS】【Nuttx】【周邊】文檔構建渲染:Sphinx 配置文件

【聲明】本博客所有內容均為個人業余時間創作&#xff0c;所述技術案例均來自公開開源項目&#xff08;如Github&#xff0c;Apache基金會&#xff09;&#xff0c;不涉及任何企業機密或未公開技術&#xff0c;如有侵權請聯系刪除 背景 接之前 blog 【OS】【Nuttx】【周邊】文…

轉換一個python項目到moonbit,碰到報錯輸出:編譯器對workflow.mbt文件中的類方法要求不一致的類型注解,導致無法正常編譯

先上結論&#xff1a;現在是moon test的時候有很多報錯&#xff0c;消不掉。問題在Trae中用GLM-4.5模型&#xff0c;轉換一個python項目到moonbit&#xff0c;碰到報錯輸出&#xff1a;報錯輸出經過多次嘗試修復&#xff0c;我發現這是一個MoonBit編譯器的bug。編譯器對workflo…

【C#補全計劃】事件

一、事件的概念1. 事件是基于委托的存在&#xff0c;是委托的安全包裹&#xff0c;讓委托的使用更具有安全性2. 事件是一種特殊的變量類型二、事件的使用1. 語法&#xff1a;event 委托類型 事件名;2. 使用&#xff1a;&#xff08;1&#xff09;事件是作為成員變量存在與類中&…

java內存緩存

我們在項目中會經常使Redis和Memcache,但是簡單項目就沒必要使用專門的緩存框架來增加系統的復雜性。用Java代碼邏輯就能實現內存級別的緩存。1.定時任務線程池使用ScheduledExecutorService結合ConcurrentHashMap&#xff0c;如果你使用的是ConcurrentHashMap&#xff0c;你可…

智能工廠生產監控大屏-vue純前端靜態頁面練習

學習前端還是非常有意思的&#xff0c;因為前端真的是可見即所得&#xff0c;可以做出來非常好看漂亮的頁面&#xff0c;最近我就在使用前端技術 做一些大屏報表&#xff0c;在制作這些大屏報表過程中&#xff0c;又熟練的練習了自己的學到的相關的前端技術&#xff0c;接下來把…

HTTP 協議詳細介紹

目錄一、HTTP 的基本概念與歷史演進1. 核心定義2. 歷史版本演進二、HTTP 的核心工作原理1. 請求-響應模型2. 基于 TCP 的傳輸&#xff08;HTTP/1.1、HTTP/2&#xff09;三、HTTP 請求結構1. 請求行2. 請求頭3. 請求體四、HTTP 響應結構1. 狀態行2. 響應頭3. 響應體五、HTTP 與 …

正則化:從過擬合到泛化的「平衡藝術」

在機器學習領域&#xff0c;有一個幾乎所有從業者都會遇到的「噩夢」&#xff1a;模型在訓練集上表現完美&#xff08;損失趨近于0&#xff09;&#xff0c;但在測試集上卻大幅「翻車」。這種現象被稱為「過擬合」&#xff08;Overfitting&#xff09;&#xff0c;它像一把雙刃…

[Python 基礎課程]根據描述定義一個 Person 類

人都屬于人類這個物種&#xff0c;每一個人都會有姓名和年齡&#xff0c;人都可以介紹自己&#xff0c;隨著時間的流逝&#xff0c;人都會增加年齡&#xff0c;每一個人都能獲取到自己的物種信息。 我們的抽象過程&#xff1a; 所有的 Person 對象都應該有一個共同的屬性來表示…

熱門手機機型重啟速度對比

以下是2023-2024年市場主流熱門手機機型的重啟速度對比分析&#xff0c;基于公開測試數據和用戶反饋整理&#xff08;數據會因系統版本和測試環境不同存在波動&#xff09;&#xff1a;旗艦機型重啟速度排名&#xff08;冷啟動&#xff09;排名機型平均重啟時間關鍵配置優化技術…

第454題.四數相加II

第454題.四數相加II 力扣題目鏈接(opens new window) 給定四個包含整數的數組列表 A , B , C , D ,計算有多少個元組 (i, j, k, l) &#xff0c;使得 A[i] B[j] C[k] D[l] 0。 為了使問題簡單化&#xff0c;所有的 A, B, C, D 具有相同的長度 N&#xff0c;且 0 ≤ N ≤…

力扣top100(day04-05)--堆

本文為力扣TOP100刷題筆記 筆者根據數據結構理論加上最近刷題整理了一套 數據結構理論加常用方法以下為該文章&#xff1a; 力扣外傳之數據結構&#xff08;一篇文章搞定數據結構&#xff09; 215. 數組中的第K個最大元素 class Solution {// 快速選擇遞歸函數int quickselect(…

CCS雙軸相位偏移光源 讓淺凹痕無處遁形

在工業檢測中&#xff0c;淺凹痕表面檢測對精度和可靠性要求極高&#xff0c;工業光源在此過程中扮演著關鍵角色&#xff0c;工業光源通過精準的光學設計&#xff08;角度、波長、強度&#xff09;將肉眼不可見的淺凹痕轉化為可量化的光學信號&#xff0c;是實現高精度自動化檢…