文章目錄
- 前言
- 1.vector的介紹及使用
- 1.1 vector的介紹
- 1.2 vector的使用
- 1.2.1 vector的定義
- 1.2.2 vector iterator 的使用
- 1.2.3 vector 空間增長問題
- 1.2.3 vector 增刪查改
- 1.2.4 vector 迭代器失效問題。(重點!!!!!!)
- 1.2.5 vector 在OJ中有關的練習題
- 2.vector深度剖析及模擬實現
- 2.1 std::vector的核心框架接口的模擬實現dzj::vector
- 本文章內容后續會完善一些!!!
- 總結
前言
提示:這里可以添加本文要記錄的大概內容:
C++中的vector是一個強大而靈活的動態數組容器,它提供了在運行時動態增長和收縮的能力,極大地簡化了數組的管理。vector是標準模板庫(STL)中的一部分,為程序員提供了高效的數據存儲和操作方式。在本博客中,我們將深入介紹vector的基本用法,并進行深度剖析和模擬實現,以幫助你更好地理解和利用這一重要的C++容器。
提示:以下是本篇文章正文內容,下面案例可供參考
1.vector的介紹及使用
1.1 vector的介紹
vector文檔介紹
vector是一個動態數組容器,它以模板類的形式實現,能夠存儲同一類型的元素。其最顯著的特點之一是能夠在運行時動態調整數組大小,而不需要手動管理內存。通過push_back()進行元素的追加、pop_back()進行末尾元素的刪除,以及使用迭代器進行元素的遍歷,vector提供了簡單而強大的操作方式。
vector的內部實現采用動態數組,這意味著它能夠在需要時自動分配更多的內存空間,以適應元素的增加。這種機制確保了vector的高效性,使得它適用于各種規模和類型的數據集。
參考文獻:
Josuttis, N. M. (2007). The C++ Standard Library: A Tutorial and Reference (2nd Edition). Addison-Wesley.
Stroustrup, B. (2013). The C++ Programming Language (4th Edition). Addison-Wesley.
Meyers, S. (2001). Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley.
1.2 vector的使用
vector學習時一定要學會查看文檔
:vector文檔介紹,vector在實際中非常的重要,在實際中我們熟悉常見的接口就可以,下面列出了哪些接口是要重點掌握的。
1.2.1 vector的定義
#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v1;//無參構造v1.push_back(0);v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);for (int i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;vector<int> v2(v1);v2.push_back(8);v2.push_back(8);v2.push_back(8);for (int i = 0; i < v2.size(); i++){cout << v2[i] << " ";}cout << endl;return 0;
}
1.2.2 vector iterator 的使用
圖解:
#include <iostream>
#include <vector>
using namespace std;
void Print1(const vector<int>&v)//正向遍歷
{vector<int>::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;
}
void Print2(const vector<int>& v)//反向遍歷
{vector<int>::const_reverse_iterator it = v.rbegin();while (it != v.rend()){cout << *it << " ";it++;}cout << endl;
}
int main()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);Print1(v1);Print2(v1);// 使用迭代器進行修改vector<int>::iterator it = v1.begin();while (it != v1.end()){*it *= 2;it++;}Print1(v1);Print2(v1);return 0;
}
1.2.3 vector 空間增長問題
-
capacity的代碼在vs和g++下分別運行會發現,vs下capacity是按1.5倍增長的,g++是按2倍增長的。
這個問題經常會考察,不要固化的認為,順序表增容都是2倍,具體增長多少是根據具體的需求定義
的。vs是PJ版本STL,g++是SGI版本STL。 -
reserve只負責開辟空間,如果確定知道需要用多少空間,reserve可以緩解vector增容的代價缺陷問題。
-
resize在開空間的同時還會進行初始化,影響size。
// vector::capacity
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;cout << "making v growing!!!!" << endl;cout << "capacity changed:" << v.capacity() << endl;for (int i = 0; i < 100; i++){v.push_back(i);if (v.size() == v.capacity())cout << "capacity changed:" << v.capacity() << endl;}return 0;
}
運行結果:
// vector::reserve
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;for (int i = 0; i < 100; i++){v.push_back(i);}cout << "size:" << v.size()<<endl;cout << "capacity:" << v.capacity()<<endl;v.reserve(200);cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;return 0;
}
運行結果:
// vector::resize
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;//for (int i = 0; i < 100; i++)//{// v.push_back(i);//}cout << "size:" << v.size()<<endl;cout << "capacity:" << v.capacity()<<endl;v.resize(200);cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;v.resize(100);cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;v.resize(101,8);cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;for (auto e : v){cout << e << " ";}return 0;
}
運行結果:
1.2.3 vector 增刪查改
// push_back/pop_back
#include <iostream>
#include <vector>
using namespace std;
int main()
{int arr[] = { 1,2,3,4 };vector<int> v(arr, arr + sizeof(arr) / sizeof(arr[0]));v.push_back(5);v.push_back(6);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it<<" ";it++;}cout << endl;v.pop_back();v.pop_back();it = v.begin();while (it != v.end()){cout << *it << " ";it++;}return 0;
}
// push_back/pop_back
運行結果:
// find / insert / erase
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator pos = find(v.begin(), v.end(), 3);v.insert(pos, 0);for (auto e : v){cout << e << " ";}cout << endl;pos = find(v.begin(), v.end(), 3);v.erase(pos);for (auto e : v){cout << e << " ";}return 0;
}
運行結果:
// operator[]+index 和 C++11中vector的新式for+auto的遍歷
// vector使用這兩種遍歷方式是比較便捷的。
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v = { 1,2,3,4 };//operator[]+indexfor (int i = 0; i < v.size(); i++){cout << v[i]<<" ";}cout << endl;for (int i = 0; i < v.size(); i++){v[i] *= 2;}vector<int> swapv;swapv.swap(v);for (auto e : swapv){cout << e << " ";}return 0;
}
運行結果:
1.2.4 vector 迭代器失效問題。(重點!!!)
迭代器的主要作用就是讓算法能夠不用關心底層數據結構,其底層實際就是一個指針,或者是對指針進行了所謂的封裝,比如:vector的迭代器就是原生態指針T*。因此迭代器失效,實際就是迭代器底層對應指針所指向的空間被銷毀了,而使用一塊已經被釋放的空間,造成的后果是程序崩潰(即如果繼續使用已經失效的迭代器,程序可能會崩潰)。
對于vector可能會導致其迭代器失效的操作有
- 會引起其底層空間改變的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、
push_back等。
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v = { 1,2,3,4 };auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}v.reserve(100);while (it != v.end()){cout << *it << " ";++it;}return 0;
}
運行錯誤:
出錯原因:以上操作,都有可能會導致vector擴容,也就是說vector底層原理舊空間被釋放掉
,而在打印時,it還使用的是釋放之間的舊空間,在對it迭代器操作時,實際操作的是一塊已經被釋放
的空間,而引起代碼運行時崩潰。
解決方式:在以上操作完成之后,如果想要繼續通過迭代器操作vector中的元素,只需給it重新賦值即可。
2. 指定位置元素的刪除操作–erase
#include <iostream>
using namespace std;
#include <vector>
int main()
{int a[] = { 1, 2, 3, 4 };vector<int> v(a, a + sizeof(a) / sizeof(int));// 使用find查找3所在位置的iteratorvector<int>::iterator pos = find(v.begin(), v.end(), 3);// 刪除pos位置的數據,導致pos迭代器失效。v.erase(pos);cout << *pos << endl; // 此處會導致非法訪問return 0;
}
erase刪除pos位置元素后,pos位置之后的元素會往前搬移,沒有導致底層空間的改變,理論上講迭代器不應該會失效,但是:如果pos剛好是最后一個元素,刪完之后pos剛好是end的位置,而end位置是沒有元素的,那么pos就失效了。因此刪除vector中任意位置上元素時
,vs就認為該位置迭代器失效了。
迭代器失效解決辦法:在使用前,對迭代器重新賦值即可
1.2.5 vector 在OJ中有關的練習題
- 只出現一次的數字i
- 楊輝三角OJ
- 刪除排序數組中的重復項 OJ
- 只出現一次的數ii OJ
- 只出現一次的數iii OJ
- 數組中出現次數超過一半的數字 OJ
- 電話號碼字母組合OJ
- 連續子數組的最大和 OJ
2.vector深度剖析及模擬實現
2.1 std::vector的核心框架接口的模擬實現dzj::vector
模擬實現代碼
本文章內容后續會完善一些!!!
總結
通過本文的閱讀,我們詳細了解了C++中vector的基本概念、使用方法和一些關鍵特性。從動態數組的角度深度剖析了vector的內部機制,以及通過模擬實現進一步加深了對其工作原理的理解。vector的靈活性和高效性使其成為C++編程中不可或缺的工具,無論是在簡單的數組操作還是復雜的數據結構中,都能展現其強大的應用價值。通過學習和研究vector,我們能夠更好地優化代碼、提高程序的效率,為C++編程帶來更多便利。希望本文對你在使用和理解C++中的vector時有所幫助。