【C++入門到精通】C++入門 —— vector (STL)


閱讀導航

  • 前言
  • 一、vector簡介
    • 1. 概念
    • 2. 特點
  • 二、vector的使用
    • 1.vector 構造函數
    • 2. vector 空間增長問題
      • ?resize 和 reserve 函數
    • 3. vector 增刪查改
      • ?operator[] 函數
  • 三、迭代器失效
  • 溫馨提示

前言

前面我們講了C語言的基礎知識,也了解了一些數據結構,并且講了有關C++的命名空間的一些知識點以及關于C++的缺省參數、函數重載,引用 和 內聯函數也認識了什么是類和對象以及怎么去new一個 ‘對象’ ,也相信大家都掌握的不錯,接下來博主將會帶領大家繼續學習有關C++比較重要的知識點——STL(vector)。下面話不多說坐穩扶好咱們要開車了😍

一、vector簡介

1. 概念

std::vector是C++標準庫中的一個容器類模板,是一種動態數組,可以存儲相同類型的元素。它提供了動態調整大小、快速隨機訪問、插入和刪除元素的操作。(vector的官方介紹鏈接)

2. 特點

  1. 動態調整大小std::vector會自動處理內存的分配和釋放,可以根據需要在運行時動態調整容器的大小。當添加或刪除元素時,std::vector會自動調整內部數組的大小以適應新的元素數量。

  2. 快速隨機訪問std::vector中的元素在內存中是連續存儲的,因此可以通過下標或迭代器快速訪問任意位置的元素。具有常數時間復雜度的隨機訪問使得std::vector非常適合需要頻繁訪問元素的場景。

  3. 動態增長和收縮:當需要添加更多元素時,std::vector會自動擴展內部數組的大小,以容納新的元素;而當需要刪除元素時,std::vector會自動收縮內部數組的大小,以減少內存的使用。

  4. 插入和刪除操作std::vector提供了插入和刪除元素的方法。可以在指定位置插入一個或多個元素,也可以通過下標或迭代器刪除指定位置的元素。

  5. 元素的訪問和遍歷:可以通過下標或迭代器訪問指定位置的元素。使用迭代器可以對std::vector進行遍歷,包括正向和反向遍歷。

  6. 其他功能:除了上述基本功能外,std::vector還提供了其他一些有用的功能,如獲取容器的大小、判斷容器是否為空、重新分配容器的大小、與其他容器進行交換、排序等。

注意:使用std::vector需要包含頭文件<vector>,命名空間為 stdstd::vector是一個模板類,需要指定存儲的元素類型,如std::vector<int>表示存儲int類型的元素。

二、vector的使用

1.vector 構造函數

std::vector 提供了多個構造函數來創建和初始化向量,這些構造函數使得創建 std::vector 對象變得靈活,并提供了多種初始化向量的方式。選擇適當的構造函數取決于具體的需求和數據源。

  1. 默認構造函數
vector()

該構造函數創建一個空的 std::vector 對象。

  1. 大小和初始值構造函數
vector(size_type count, const T& value = T())

該構造函數創建一個包含 count 個元素的 std::vector 對象,并用 value 的值初始化每個元素。如果未提供 value 的值,則使用類型 T 的默認構造函數進行初始化。

  1. 范圍構造函數
template <class InputIt>
vector(InputIt first, InputIt last)

該構造函數使用迭代器范圍 [first, last) 中的元素創建一個 std::vector 對象。可以通過傳遞兩個迭代器來指定范圍,從而將其他容器中的元素復制到新的 std::vector 對象中。

  1. 拷貝構造函數
vector(const vector& other)

該構造函數創建一個與 other 相同的 std::vector 對象,復制 other 中的所有元素。

  1. 移動構造函數
vector(vector&& other)

該構造函數使用 other 的資源來創建一個新的 std::vector 對象,同時將 other 置為空。

  1. 初始化列表構造函數
vector(std::initializer_list<T> init)

該構造函數使用花括號 {} 內的元素列表初始化 std::vector 對象。可以通過傳遞元素的列表來創建和初始化向量。

下面是所有使用構造函數創建 std::vector 對象的代碼:

#include <vector>
#include <iostream>int main() {// 默認構造函數std::vector<int> numbers;  // 空的向量// 大小和初始值構造函數[10, 10, 10, 10, 10]std::vector<int> numbers1(5, 10); // 范圍構造函數[1, 2, 3, 4, 5]std::vector<int> numbers2 = {1, 2, 3, 4, 5};  // 拷貝構造函數[1, 2, 3, 4, 5]std::vector<int> numbers3 = numbers2;  // 移動構造函數[1, 2, 3, 4, 5]std::vector<int> numbers4 = std::move(numbers2);  // numbers2 現在為空// 初始化列表構造函數[1, 2, 3, 4, 5]std::vector<int> numbers5 {1, 2, 3, 4, 5}; // 輸出向量內的元素for (const auto& num : numbers5) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

2. vector 空間增長問題

std::vector 中,空間增長(space growth)是指在向向量添加元素時,當容量不足時,向量自動增加內部存儲空間的過程。這是為了確保向量能夠容納更多的元素,并減少頻繁的內存重新分配操作。

  1. 容量和大小
  • 大小(size):指的是 std::vector 中當前擁有的元素個數。

  • 容量(capacity):指的是 std::vector 內部存儲空間的大小,即它可以容納的元素個數。

  1. 空間分配器(allocator)

std::vector 使用內部的空間分配器來動態管理存儲空間。默認情況下,它使用標準全局的 operator newoperator delete 來分配和釋放內存。也可以提供自定義的空間分配器來滿足特定的需求。

  1. 容量增長策略

std::vector 使用一種策略來決定何時以及如何增加內部存儲空間的容量:

  • 固定增長因子:許多實現會以固定的因子(例如2倍)來增加容量。這意味著每次增長時,容量都會以固定比例增加。這種策略通常具有較好的性能,但可能會占用更多的內存。

  • 線性增長:某些實現會以固定的大小(如每次增加n個元素)增加容量。這可以提供更節省內存的方式,但在某些情況下可能導致頻繁的重新分配操作。

容量增長過程通常包括以下步驟:

  1. std::vector 判斷當前的容量是否能夠容納新的元素。如果容量不足,進入空間增長階段。

  2. 分配新的更大的內部存儲空間。這通常涉及到申請更大的內存塊,并將已有的元素從舊的內存塊拷貝到新的內存塊中。

  3. 釋放舊的內部存儲空間,回收內存資源。

  4. 更新 std::vector 的容量信息,以反映新的內部存儲空間大小。

空間增長的頻率取決于添加元素的數量和容器的策略。過于頻繁的空間增長可能會導致性能下降,因為內存重新分配和元素拷貝都是開銷較大的操作。因此,預先分配一定容量的空間(使用 std::vector::reserve())可以減少空間增長的次數,提高性能。

注意:自定義類型的元素在空間增長過程中會涉及到拷貝構造函數和析構函數的調用。確保自定義類型的正確實現這些特殊函數是非常重要的,以避免潛在的內存錯誤和資源泄漏。

?resize 和 reserve 函數

在 C++ 的 std::vector 中,reserve()resize() 是兩個用于管理向量容量和大小的成員函數。

  1. reserve(n)

reserve() 函數用于預留至少能夠容納 n 個元素的內部存儲空間,而不會改變向量的大小。這樣做是為了避免頻繁的重新分配和拷貝操作,提高性能。

調用 reserve(n) 后,如果 n 大于當前容量(capacity()),則向量會重新分配新的內部存儲空間,容量會大于等于 n。如果 n 小于或等于當前容量,則不會有任何變化。

void reserve(size_type n);
  1. resize(n, value)

resize() 函數用于改變向量的大小,并根據需要添加或刪除元素。

  • 如果 n 小于當前大小(size()),則會刪除超出 n 個元素后的元素,向量的大小變為 n
  • 如果 n 大于當前大小,則會添加足夠的元素,以便向量的大小變為 n。添加的元素將使用 value 進行初始化。
void resize(size_type n);
void resize(size_type n, const value_type& value);

注意:如果增加了向量的大小,新添加的元素(在當前大小和 n 之間)將通過拷貝構造函數進行初始化。如果存儲的是自定義類型的元素,確保該類型的拷貝構造函數正確實現是很重要的。

以下是 reserve()resize() 的示例代碼:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers;numbers.reserve(10);  // 預留至少能容納 10 個元素的空間std::cout << "Capacity: " << numbers.capacity() << std::endl;  // 輸出容量numbers.resize(5);  // 更改大小為 5std::cout << "Size after resize: " << numbers.size() << std::endl;  // 輸出大小numbers.resize(8, 42);  // 更改大小為 8,并用值 42 進行初始化std::cout << "Size after resize 2: " << numbers.size() << std::endl;  // 輸出大小return 0;
}

總的來說,reserve() 用于預留足夠的存儲空間以容納更多的元素,而 resize() 用于改變向量的大小并根據需要添加或刪除元素。這兩個函數可以幫助我們靈活地管理 std::vector 的容量和大小,以滿足不同的需求。

3. vector 增刪查改

當使用 C++ 的 std::vector 容器時,可以使用下面的方法來執行向向量中增加數據、刪除數據、查找數據和修改數據的操作。

  1. 增加數據

std::vector 中增加數據可以使用 push_back() 函數將元素添加到向量的末尾。

void push_back(const T& value);

使用示例:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers;numbers.push_back(10);numbers.push_back(20);numbers.push_back(30);for (const auto& num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
  1. 刪除數據

可以使用 erase() 函數從向量中刪除數據。它接受一個迭代器參數,指示要刪除的元素位置。

iterator erase(iterator position);

使用示例:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers = {10, 20, 30};numbers.erase(numbers.begin() + 1);  // 刪除索引為 1 的元素for (const auto& num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
  1. 查找數據

可以使用 std::find() 算法函數在向量中查找特定的元素。該函數接受兩個迭代器參數,指示要搜索的范圍,以及要查找的值。它返回指向找到的元素的迭代器,如果未找到,則返回指向容器末尾的迭代器。

iterator find(iterator first, iterator last, const T& value);

使用示例:

#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> numbers = {10, 20, 30};auto it = std::find(numbers.begin(), numbers.end(), 20);if (it != numbers.end()) {std::cout << "Element found at index: " << std::distance(numbers.begin(), it) << std::endl;} else {std::cout << "Element not found" << std::endl;}return 0;
}
  1. 修改數據

可以通過迭代器來訪問和修改 std::vector 中的元素。通過修改迭代器指向的元素來實現數據的修改。

使用示例:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers = {10, 20, 30};auto it = numbers.begin();++it;*it = 25;  // 修改元素值for (const auto& num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

?operator[] 函數

還可以使用 operator[] 運算符來訪問 std::vector 中的元素并進行修改。operator[] 函數的官方鏈接

operator[] 運算符允許通過索引來訪問向量中的元素,并提供了對元素的非常快速的隨機訪問。索引從 0 開始,依次增加。

使用示例:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers = {10, 20, 30};std::cout << numbers[0] << std::endl;  // 訪問索引為 0 的元素numbers[1] = 25;  // 修改索引為 1 的元素的值for (const auto& num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

需要注意以下幾點:

  1. 使用 operator[] 訪問索引超出向量范圍的元素是未定義行為,因此要確保索引值在有效范圍內。

  2. 如果要對不存在的元素使用 operator[] 進行訪問,它將創建一個新元素并分配給該索引位置。因此,在使用 operator[] 之前,通常需要確保向量具有足夠的大小。

  3. operator[] 返回對索引位置的引用,因此可以通過返回的引用進行修改和賦值操作。

operator[] 運算符是一種快速訪問和修改 std::vector 中元素的便捷方式,它提供了類似于數組的索引操作。

三、迭代器失效

std::vector 中,迭代器失效指的是當在向量進行插入或刪除操作后,原本指向向量元素的迭代器可能會失效,即不能再安全地使用。

迭代器失效的問題存在于插入和刪除操作中,因為這些操作可能會導致向量重新分配內存,使得原來的迭代器指向的位置變得無效。下面是常見的迭代器失效情況:

  1. 在插入或刪除一個元素后,迭代器失效

當向向量中插入或刪除元素時,迭代器可能會失效。插入操作可能導致內部存儲重新分配,而刪除操作可能使元素位置向前移動。這會導致之前的迭代器指向的位置變得無效。

std::vector<int> numbers = {10, 20, 30};
auto it = numbers.begin();numbers.insert(it + 1, 15);  // 在索引為 1 的位置插入元素// 在插入之后,迭代器 it 可能失效,不能再使用
  1. 使用被刪除元素的迭代器,迭代器失效

當使用被刪除元素的迭代器繼續訪問向量時,迭代器可能會失效。因為刪除元素會導致元素位置的變動,原本的迭代器指向的位置可能已經被其他元素占據。

std::vector<int> numbers = {10, 20, 30};
auto it = numbers.begin();numbers.erase(it);  // 刪除首個元素// 在刪除之后,迭代器 it 變成無效的迭代器,不能再使用

為了避免迭代器失效問題,可以采取以下幾種方法:

  • 使用索引替代迭代器:使用基于索引的訪問方式,而不是依賴迭代器。

  • 在插入或刪除元素后重新獲取迭代器:在插入或刪除操作后,重新獲取迭代器,而不是繼續使用之前的迭代器。

std::vector<int> numbers = {10, 20, 30};
auto it = numbers.begin();numbers.insert(it + 1, 15);
it = numbers.begin();  // 插入后重新獲取迭代器numbers.erase(it);
it = numbers.begin();  // 刪除后重新獲取迭代器
  • 使用算法和函數:使用標準庫提供的算法和函數,而不是手動操作迭代器。這些函數會處理好迭代器失效的情況,例如使用 std::for_each 遍歷向量。
std::vector<int> numbers = {10, 20, 30};
std::for_each(numbers.begin(), numbers.end(), [](int& num) {// 修改元素值
});

了解迭代器失效的情況,并采取適當的措施來避免迭代器失效問題,是在操作 std::vector 時需要注意的重要方面。

溫馨提示

感謝您對博主文章的關注與支持!在閱讀本篇文章的同時,我們想提醒您留下您寶貴的意見和反饋。如果您喜歡這篇文章,可以點贊、評論和分享給您的同學,這將對我提供巨大的鼓勵和支持。另外,我計劃在未來的更新中持續探討與本文相關的內容。我會為您帶來更多關于C++以及編程技術問題的深入解析、應用案例和趣味玩法等。請繼續關注博主的更新,不要錯過任何精彩內容!

再次感謝您的支持和關注。我們期待與您建立更緊密的互動,共同探索C++、算法和編程的奧秘。祝您生活愉快,排便順暢!
在這里插入圖片描述

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

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

相關文章

軟件測試基礎篇——Docker

1、docker技術概述 docker描述&#xff1a;docker是一項虛擬化的容器技術&#xff08;類似于虛擬機&#xff09;&#xff0c;docker技術給使用者提供一個平臺&#xff0c;在該平臺上可以利用提供的容器&#xff0c;對每一個應用程序進行單獨的封裝隔離&#xff0c;每一個應用程…

spring 2.7.14 cors 設置 allowedOrigins(“*“)通配符 失效怎么解決

失效代碼&#xff1a; package com.yukuanyan.searcher_web.config;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebM…

計算機競賽 opencv python 深度學習垃圾圖像分類系統

0 前言 &#x1f525; 優質競賽項目系列&#xff0c;今天要分享的是 &#x1f6a9; opencv python 深度學習垃圾分類系統 &#x1f947;學長這里給一個題目綜合評分(每項滿分5分) 難度系數&#xff1a;3分工作量&#xff1a;3分創新點&#xff1a;4分 這是一個較為新穎的競…

圖像的伽馬變換

伽馬變換&#xff08;Gamma Correction&#xff09;是一種在圖像處理中常用的非線性變換方法&#xff0c;用于調整圖像的亮度和對比度。它在圖像的像素值上應用一個冪次函數&#xff0c;以改變圖像的灰度級分布&#xff0c;從而影響圖像的感知亮度。伽馬變換通常用于糾正顯示器…

Monkey測試真的靠譜嗎?

Monkey測試&#xff0c;顧名思義&#xff0c;就是模擬一只猴子在鍵盤上亂敲&#xff0c;從而達到測試被測系統的穩定性。Monkey測試&#xff0c;是Android自動化測試的一種手段&#xff0c;Monkey測試本身非常簡單&#xff0c;Android SDK 工具支持adb Shell命令&#xff0c;實…

208、仿真-51單片機脈搏心率與心電報警Proteus仿真設計(程序+Proteus仿真+配套資料等)

畢設幫助、開題指導、技術解答(有償)見文未 目錄 一、硬件設計 二、設計功能 三、Proteus仿真圖 四、程序源碼 資料包括&#xff1a; 需要完整的資料可以點擊下面的名片加下我&#xff0c;找我要資源壓縮包的百度網盤下載地址及提取碼。 方案選擇 單片機的選擇 方案一&a…

ElasticSearch 7.4學習記錄(基礎概念和基礎操作)

若你之前從未了解過ES&#xff0c;本文將由淺入深的一步步帶你理解ES&#xff0c;簡單使用ES。作者本人就是此狀態&#xff0c;通過學習和梳理&#xff0c;產出本文&#xff0c;已對ES有個全面的了解和想法&#xff0c;不僅將知識點梳理&#xff0c;也涉及到自己的理解&#xf…

行業追蹤,2023-08-09

自動復盤 2023-08-09 凡所有相&#xff0c;皆是虛妄。若見諸相非相&#xff0c;即見如來。 k 線圖是最好的老師&#xff0c;每天持續發布板塊的rps排名&#xff0c;追蹤板塊&#xff0c;板塊來開倉&#xff0c;板塊去清倉&#xff0c;丟棄自以為是的想法&#xff0c;板塊去留讓…

linux學習——Redis基礎

目錄 一、noSQL 類型 特點及應用場景 二、Redis 三、安裝方式 編譯安裝 rpm安裝 四、目錄結構 /etc/redis.conf 五、Redis命令 六、本地登錄和遠程登錄 本地登錄 遠程登錄 七、數據庫操作 幫助信息 庫操作 數據操作 八、Redis持久化 一、RDB類型 二、AOF模式 一…

2023河南萌新聯賽第(四)場:河南大學 F - 小富的idea

2023河南萌新聯賽第&#xff08;四&#xff09;場&#xff1a;河南大學 F - 小富的idea 時間限制&#xff1a;C/C 1秒&#xff0c;其他語言2秒 空間限制&#xff1a;C/C 262144K&#xff0c;其他語言524288K 64bit IO Format: %lld 題目描述 要注意節約 卷王小富最近又在內卷&a…

密碼檢查-C語言/Java

描述 小明同學最近開發了一個網站&#xff0c;在用戶注冊賬戶的時候&#xff0c;需要設置賬戶的密碼&#xff0c;為了加強賬戶的安全性&#xff0c;小明對密碼強度有一定要求&#xff1a; 1. 密碼只能由大寫字母&#xff0c;小寫字母&#xff0c;數字構成&#xff1b; 2. 密碼不…

偽類和偽元素有何區別?

聚沙成塔每天進步一點點 ? 專欄簡介? 偽類&#xff08;Pseudo-class&#xff09;? 偽元素&#xff08;Pseudo-element&#xff09;? 區別總結? 寫在最后 ? 專欄簡介 前端入門之旅&#xff1a;探索Web開發的奇妙世界 記得點擊上方或者右側鏈接訂閱本專欄哦 幾何帶你啟航前…

信號調制原理演示,模擬和數字調制技術大比拼

【中英雙語字幕】信號調制原理演示&#xff0c;模擬和數字調制技術大比拼&#xff01;_嗶哩嗶哩_bilibili

騰訊云輕量應用服務器Typecho應用模板搭建博客流程

騰訊云百科分享使用騰訊云輕量應用服務器Typecho應用模板搭建博客流程&#xff0c;Typecho 是開源的博客建站平臺&#xff0c;具有輕量、高效、穩定等特點&#xff0c;操作界面簡潔友好。該鏡像基于 CentOS 7.6 64 位操作系統&#xff0c;并已預置 Nginx、PHP、MariaDB 軟件。您…

4.0 Python 變量與作用域

在python中&#xff0c;變量的作用域決定了變量在哪些位置可以被訪問。一個程序中的變量并不是所有的地方都可以訪問的&#xff0c;其訪問權限決定于變量的賦值位置。python中有兩種最基本的變量作用域&#xff1a;局部作用域和全局作用域。局部變量是在函數內部定義的變量&…

day24-106.從中序與后序遍歷序列構造二叉樹

106.從中序與后序遍歷序列構造二叉樹 力扣題目鏈接(opens new window) 根據一棵樹的中序遍歷與后序遍歷構造二叉樹。 注意: 你可以假設樹中沒有重復的元素。 例如&#xff0c;給出 中序遍歷 inorder [9,3,15,20,7]后序遍歷 postorder [9,15,7,20,3] 返回如下的二叉樹&am…

前端跨域問題解決方法

跨域是WEB瀏覽器專有的同源限制訪問策略。(后臺接口調用和postman等工具會出現) 跨源資源共享&#xff08;CORS&#xff0c;或通俗地譯為跨域資源共享&#xff09;是一種基于 HTTP 頭的機制&#xff0c;該機制通過允許服務器標示除了它自己以外的其他源&#xff08;域、協議或端…

java項目打包運行報異常:Demo-1.0-SNAPSHOT.jar中沒有主清單屬性

檢查后發現pom文件中有錯誤&#xff0c;需要添加build內容才能恢復正常。 添加下面文件后再次啟動恢復正常。 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactI…

C語言atoi函數將字符串類型轉換為整型

atoi() 是C標準庫中的一個函數&#xff0c;用于將字符串轉換為整數。函數原型如下&#xff1a; int atoi(const char *str); 參數 str 是一個指向要轉換的字符串的指針。atoi() 函數會嘗試將字符串中的數字部分轉換為整數&#xff0c;并返回轉換后的整數值。如果字符串中不僅包…

Add-in Express for Microsoft Office and Delphi Crack

Add-in Express for Microsoft Office and Delphi Crack 適用于Microsoft Office和Delphi VCL的Add-in Express使您能夠在幾次點擊中為Microsoft Office開發專業插件。它生成基于COM的項目&#xff0c;這些項目包含Microsoft Office外接程序或智能標記的所有必要功能&#xff0…