vector學習時一定要學會查看reference
目錄
前言
一、vector基本概念
1.1vector是什么?
1.2內存管理
二、vector的使用
2.1vector的構造
2.2vector iterator 的使用?
2.3vector 空間增長問題?
2.4vector的元素訪問?
?2.5vector 增刪查改
?總結
前言
在C++編程中,vector ? 是標準模板庫(STL)中最常用的數據結構之一。它是一個封裝了動態大小數組的序列容器,提供了靈活的內存管理方式和高效的元素訪問機制。小編將介紹 ? vector ? 的基本特性、常用操作,幫助你更好地理解和掌握這一強大的工具。
一、vector基本概念
1.1vector是什么?
?vector是表示可變大小數組的序列容器。
- ?vector就像數組一樣,vector也采用的連續存儲空間來存儲元素。也就是意味著可以采用下標對vector的元素進行訪問,和數組一樣高效。但是又不像數組,它的大小是可以動態改變的,而且它的大小會被容器自動處理
- 與普通的數組相比, ?vector ? 的大小可以動態變化,能夠根據需要自動擴展或收縮。它通過模板實現,可以存儲任意類型的元素,如整數、浮點數、字符串等。
1.2內存管理
?vector ? 在內部使用動態分配的內存來存儲元素。當向 ? vector ? 中添加元素時,如果當前分配的內存不足以容納新元素, ?vector ? 會自動分配一塊更大的內存,并將原有元素復制到新的內存中。這個過程稱為“擴容”。擴容操作雖然在某些情況下會帶來性能開銷,但 ? vector ? 通過合理的內存分配策略(如每次擴容時將容量加倍)盡量減少了擴容的頻率。
二、vector的使用
2.1vector的構造
?空容器構造函數 (默認構造函數)
構造一個空容器,沒有元素。
#include <iostream>
#include <vector>
using namespace std;
int main ()
{// constructors used in the same order as described above:vector<int> first; // 無參構造return 0;
}
?填寫構造函數
構造一個容器n元素。每個元素都是val(如果提供)。
int main ()
{std::vector<int> second (4,100); // 構造并初始化n個valreturn 0;
}
范圍構造函數
構造一個包含與范圍一樣多的元素的容器[begin(),end()),與每個元素emplace-構造從該范圍內的相應元素,以相同的順序。
int main ()
{vector<int> second (4,100); // vector<int> third (second.begin(),second.end()); // 使用迭代器進行初始化構造return 0;
}
?(迭代器目前可以認為是指針)
?拷貝構造函數
int main ()
{vector<int> second (4,100); // four ints with value 100vector<int> third (second.begin(),second.end()); // iterating through secondvector<int> fourth (third); //?拷貝構造return 0;
}
?
2.2vector iterator 的使用?
?獲取第一個數據位置的iterator/const_iterator:
獲取最后一個數據的下一個位置的iterator/const_iterator
獲取最后一個數據位置的reverse_iterator
?獲取第一個數據前一個位置的reverse_iterator
?
?
?
?
2.3vector 空間增長問題?
?獲取數據個數:
?
?獲取容量大小:
capacity的代碼在vs和g++下分別運行會發現,vs下capacity是按1.5倍增長的,g++是按2倍增長的。
這個問題經常會考察,不要固化的認為,vector增容都是2倍,具體增長多少是根據具體的需求定義的。vs是PJ版本STL,g++是SGI版本STL。?
?
?判斷是否為空:
?
?改變vector的size:
- resize 指定的數據個數如果大于當前一段空間上的有效數據個數那么如果不指定數據會使用 0 作為有效數據追加在原數據序列后面,讓有效字符個數變為指定字符個數,并且空間不夠會擴容開空間,如果我們指定了數據則會使用我們指定的數據作為有效數據追加在原數據序列的后面
- resize指定的數據個數如果小于當前有效數據個數,那么會將有效數據個數修改為指定數據個數,并且底層空間大小保持不變
??
?改變vector的capacity:
reserve只負責開辟空間,如果確定知道需要用多少空間,reserve可以緩解vector增容的代價缺陷問題。
- reserve 會一次性擴容開空間,如果你預想開的空間大于當前空間大小,那么開好的空間相較于你預期想要開的空間只多不少,reverse一般用于你提前已經預想好開多大空間了,這樣使用reserve進行提前一次性開好空間提高效率,避免多次開空間
- 如果你預想開的空間小于等于當前空間大小,那么當前空間大小保持不變
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
cout<<v.size();
cout<<v.capacity();
v.resize(10);
cout<<v.size();
v.reserve(10);
cout<<capacity();
return 0;
}
?
2.4vector的元素訪問?
?
?operator[] :用于提供對容器或數組中元素的快速訪問
與 ? at() ? 的區別:
operator[] ?:
? 不進行邊界檢查。如果索引超出范圍,行為是未定義的(可能導致程序崩潰)。
? 返回的是元素的引用,可以直接修改元素的值。
? 性能較高,因為它不進行額外的檢查。
?at() ?:
? 進行邊界檢查。如果索引超出范圍,會拋出 ? std::out_of_range ? 異常。
? 返回的是元素的引用,也可以直接修改元素的值。
? 性能略低于 ? operator[] ?,因為需要進行額外的檢查。
?
front:返回對第一個元素的引用向量。
?
?back:返回對最后一個元素的引用向量。
int main()
{int a[5] = { 1,2,3,4,5 };vector<int> v(a, a + 5);cout << v.at(1) << endl;cout << v.front() << endl;cout << v.back() << endl;return 0;
}
?
?2.5vector 增刪查改
push_back:尾插
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
return 0;
}
?
pop_back:尾刪
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.pop_back();return 0;
}
?
insert:在pos位置插入一個值/一個區間/n個值
int main()
{int a[5] = { 1,2,3,4,5 };vector<int> v(a, a + 5);// v=1,2,3,4,5v.insert(v.begin(), 5);//5,1,2,3,4,5for (int e : v){cout << e << ' ';}cout << endl;v.insert(v.begin(), 5 , 1);//1,1,1,1,1,5,1,2,3,4,5for (int e : v){cout << e << ' ';}cout << endl;vector<int> v0(3, 6);v.insert(v.end(), v0.begin(),v0.end());//1,1,1,1,1,5,1,2,3,4,5,6,6,6for (auto e : v){cout << e << ' ';}cout << endl;return 0;
}
?
assign:將要傳入數據的對象的原有的數據清空,再去分派數據
int main()
{string s("hello world");vector<char> v;v.assign(s.begin(), s.end());for (char e : v){cout << e;//"hello world"}cout << endl;v.assign(6,6);for (char e : v){cout << e << ' ';//6,6,6,6,6,6}cout << endl;return 0;
}
?
erase:刪除一個迭代器位置上的值并且返回這個刪除的迭代器的下一個數據的位置的迭代器
注意:由于當前迭代器位置的值已經被刪除,所以當前位置的迭代器位置的值的下一個位置的值會向前頂替當前位置的值,那么下一個數據的值就成了當前位置上的數據,返回的是當前位置的迭代器,但當前位置的迭代器上的值改變了
?
?swap:交換兩個vector的數據空間
int main()
{vector<int> v1(6, 1);vector<int> v2(6, 0);cout << "v1的數據序列為:";//1,1,1,1,1,1for (auto e : v1){cout << e << ' ';}cout << endl;cout << "v2的數據序列為:";//0,0,0,0,0,0for (auto e : v2){cout << e << ' ';}cout << endl << endl;v1.swap(v2);//v1和v2交換了數據空間cout << "v1的數據序列為:";for (auto e : v1){cout << e << ' ';//0,0,0,0,0,0}cout << endl;cout << "v2的數據序列為:";for (auto e : v2){cout << e << ' ';//1,1,1,1,1,1}cout << endl;return 0;
}
?
clear:清空vector類模板實例化出的對象的全部數據
int main()
{vector<int> v1(6, 1);v1.clear();//v1被清空return 0;
}
?總結
vector的使用場景:
- ?動態數組需求當需要一個大小可動態變化的數組時, ?vector ? 是理想的選擇。它能夠根據元素的添加和刪除自動調整內存分配,避免了手動管理內存的復雜性。
- 高效的隨機訪問 ?vector ? 支持高效的隨機訪問,通過索引可以快速獲取任意位置的元素。這使得它在需要頻繁隨機訪問元素的場景中非常高效。
- 與其他STL算法配合 ?vector ? 作為STL容器,能夠無縫地與STL算法(如排序、查找等)配合使用,從而實現復雜的數據處理邏輯。
Vector的注意事項:
- 雖然 ? vector ? 的擴容策略盡量減少了擴容的頻率,但在某些高頻插入的場景中,擴容仍然可能帶來一定的性能開銷。如果事先知道 ? vector ? 的大致大小,可以通過 ? reserve() ? 方法預先分配足夠的內存,從而避免多次擴容。
- 迭代器失效在對 ? vector ? 進行插入或刪除操作時,可能會導致迭代器失效。特別是當插入或刪除操作導致內存擴容或收縮時,所有迭代器都會失效。因此,在使用迭代器時需要注意迭代器的有效性。