文章目錄
- vector的介紹及使用
- vector的介紹
- vector的使用
- vector的定義
- vector的遍歷
- vector iterator 的使用
- vector 空間增長問題
- vector 增刪查改
- vector 迭代器失效問題
- vector 在OJ中的使用
- vector深度剖析及模擬實作
- 模擬實作vector
- 使用memcpy拷貝問題
- 對vector核心介面的測驗
vector的介紹及使用
vector的介紹
vector的檔案介紹
- vector是表示可變大小陣列的序列容器,
- 就像陣列一樣,vector也采用的連續存盤空間來存盤元素,也就是意味著可以采用下標對vector的元素進行訪問,和陣列一樣高效,但是又不像陣列,它的大小是可以動態改變的,而且它的大小會被容器自
動處理,- 本質講,vector使用動態分配陣列來存盤它的元素,當新元素插入時候,這個陣列需要被重新分配大小
為了增加存盤空間,其做法是,分配一個新的陣列,然后將全部元素移到這個陣列,就時間而言,這是一個相對代價高的任務,因為每當一個新的元素加入到容器的時候,vector并不會每次都重新分配大小,- vector分配空間策略:vector會分配一些額外的空間以適應可能的增長,因為存盤空間比實際需要的存盤空間更大,不同的庫采用不同的策略權衡空間的使用和重新分配,但是無論如何,重新分配都應該是對數增長的間隔大小,以至于在末尾插入一個元素的時候是在常數時間的復雜度完成的,
- 因此,vector占用了更多的存盤空間,為了獲得管理存盤空間的能力,并且以一種有效的方式動態增長,
- 與其它動態序列容器相比(deques, lists and forward_lists), vector在訪問元素的時候更加高效,在末尾添加和洗掉元素相對高效,對于其它不在末尾的洗掉和插入操作,效率更低,比起lists和forward_lists統一的迭代器和參考更好,
vector的使用
vector的定義
| (constructor)建構式宣告 | 介面說明 |
|---|---|
| vector()(重點) | 無參構造 |
| vector(size_type n, const value_type& val = value_type()) | 構造并初始化n個val |
| vector (const vector& x); (重點) | 拷貝構造 |
| vector (InputIterator first, InputIterator last); | 使用迭代器進行初始化構造 |
// constructing vectors
#include <iostream>
#include <vector>
int main ()
{
// 建構式的使用
std::vector<int> first; // 無參構造
std::vector<int> second (4,100); // 初始化為4個整型數字100
std::vector<int> third (second.begin(),second.end()); // 用second的迭代器初始化,類似于拷貝構造second
//也可以用其他類的迭代器初始化
string s("hello");
vector<char> v(s.begin(), s.end());
std::vector<int> fourth (third); // 拷貝構造
// 下面涉及迭代器初始化的部分,我們學習完迭代器再來看這部分
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
std::cout << "The contents of fifth are:";
for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
vector的遍歷
1.size()+operator[]
2.迭代器
3.范圍for
vector iterator 的使用
| iterator的使用 | 介面說明 |
|---|---|
| begin + end(重點) | 獲取第一個資料位置的iterator/const_iterator, 獲取最后一個資料的下一個位置 的iterator/const_iterator |
| rbegin + rend | 獲取最后一個資料位置的reverse_iterator,獲取第一個資料前一個位置的 reverse_iterator |

#include <iostream>
#include <vector>
using namespace std;
void PrintVector(const vector<int>& v)
{
// const物件使用const迭代器進行遍歷列印
vector<int>::const_iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
int main()
{
// 使用push_back插入4個資料
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
// 使用迭代器進行遍歷列印
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// 使用迭代器進行修改
it = v.begin();
while (it != v.end())
{
*it *= 2;
++it;
}
// 使用反向迭代器進行遍歷再列印
vector<int>::reverse_iterator rit = v.rbegin();
while (rit != v.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
PrintVector(v);
return 0;
}
vector 空間增長問題
| 容量空間 | 介面說明 |
|---|---|
| size | 獲取資料個數 |
| capacity | 獲取容量大小 |
| empty | 判斷是否為空 |
| resize(重點) | 改變vector的size |
| reserve (重點) | 改變vector放入capacity |
- capacity的代碼在vs和g++下分別運行會發現,vs下capacity是按1.5倍增長的,g++是按2倍增長的,
這個問題經常會考察,不要固化的認為,順序表增容都是2倍,具體增長多少是根據具體的需求定義的,vs是PJ版本STL,g++是SGI版本STL,- reserve只負責開辟空間,如果確定知道需要用多少空間,reserve可以緩解vector增容的代價缺陷問
題,- resize在開空間的同時還會進行初始化,影響size
capacity
// vector::capacity
#include <iostream>
#include <vector>
int main ()
{
size_t sz;
std::vector<int> foo;
sz = foo.capacity();
std::cout << "making foo grow:\n";
for (int i=0; i<100; ++i)
{
foo.push_back(i);
if (sz!=foo.capacity())
{
sz = foo.capacity();
std::cout << "capacity changed: " << sz << '\n';
}
}
}
vs:運行結果:
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 3
capacity changed: 4
capacity changed: 6
capacity changed: 9
capacity changed: 13
capacity changed: 19
capacity changed: 28
capacity changed: 42
capacity changed: 63
capacity changed: 94
capacity changed: 141
g++運行結果:
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 4
capacity changed: 8
capacity changed: 16
capacity changed: 32
capacity changed: 64
capacity changed: 128
reserve
// vector::reserve
#include <iostream>
#include <vector>
int main ()
{
size_t sz;
std::vector<int> foo;
sz = foo.capacity();
std::cout << "making foo grow:\n";
for (int i=0; i<100; ++i)
{
foo.push_back(i);
if (sz!=foo.capacity())
{
sz = foo.capacity();
std::cout << "capacity changed: " << sz << '\n';
}
}
std::vector<int> bar;
sz = bar.capacity();
bar.reserve(100); // this is the only difference with foo above
std::cout << "making bar grow:\n";
for (int i=0; i<100; ++i)
{
bar.push_back(i);
if (sz!=bar.capacity())
{
sz = bar.capacity();
std::cout << "capacity changed: " << sz << '\n';
}
}
return 0;
}
resize
// vector::resize
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
// set some initial content:
for (int i=1;i<10;i++)
myvector.push_back(i);
myvector.resize(5);
myvector.resize(8,100);
myvector.resize(12);
std::cout << "myvector contains:";
for (int i=0;i<myvector.size();i++)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
vector 增刪查改
| vector增刪查改 | 介面說明 |
|---|---|
| push_back | 尾插 |
| pop_back | 尾刪 |
| find | 查找,(注意這個是演算法模塊實作,不是vector的成員介面) |
| insert | 在position之前插入val |
| erase | 洗掉position位置的資料 |
| swap | 交換兩個vector的資料空間 |
| operator[] | 像陣列一樣訪問 |
push_back和pop_back的使用
// push_back/pop_back
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int a[] = { 1, 2, 3, 4 };
vector<int> v(a, a+sizeof(a)/sizeof(int));
vector<int>::iterator it = v.begin();
//用迭代器遍歷vector
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//尾刪
v.pop_back();
v.pop_back();
//尾插
v.push_back(5);
it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
結果:

find、insert、erase的使用
//insert,用迭代器插入
iterator insert (iterator position, const value_type& val);
//erase,用迭代器洗掉
iterator erase (iterator position);
//find
template <class InputIterator, class T>
//用迭代器遍歷查找,回傳的是所找元素的迭代器位置
InputIterator find (InputIterator first, InputIterator last, const T& val);
// find / insert / erase
#include <iostream>
#include <algorithm>//find的頭檔案,在演算法頭檔案里
#include <vector>
using namespace std;
int main()
{
int a[] = { 1, 2, 3, 4 };
vector<int> v(a, a + sizeof(a) / sizeof(int));
// 使用find查找3所在位置的iterator
vector<int>::iterator pos = find(v.begin(), v.end(), 3);
// 在pos位置之前插入30
v.insert(pos, 30);
//用迭代器遍歷vector
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//查找3的iterator
pos = find(v.begin(), v.end(), 3);
// 洗掉pos位置的資料
v.erase(pos);
//再次遍歷
it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
結果:

operator[]、swap的使用
// operator[]+index 和 C++11中vector的新式for+auto的遍歷
// vector使用這兩種遍歷方式是比較便捷的,
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int a[] = { 1, 2, 3, 4 };
vector<int> v(a, a + sizeof(a) / sizeof(int));
// 通過[]讀寫第0個位置,
v[0] = 10;
cout << v[0] << endl;
// 通過[i]的方式遍歷vector
for (size_t i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout << endl;
vector<int> swapv;
//v和swapv交換
swapv.swap(v);
cout << "v data:";//v的內容
for (size_t i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout << endl;
cout << "swapv data:";//swapv的內容
for (size_t i = 0; i < swapv.size(); ++i)
cout << swapv[i] << " ";
cout << endl;
// C++11支持的新式范圍for遍歷
for(auto x : v)
cout<< x << " ";
cout<<endl;
return 0;
}
結果:

C++98下,最好使用vector的swap,全域的swap會涉及深淺拷貝,開銷較大
C++11則都一樣
vector 迭代器失效問題
迭代器的主要作用就是讓演算法能夠不用關心底層資料結構,其底層實際就是一個指標,或者是對指標進行了封裝,比如:vector的迭代器就是原生態指標T*,因此迭代器失效,實際就是迭代器底層對應指標所指向的空間被銷毀了,而使用一塊已經被釋放的空間,造成的后果是程式崩潰(即如果繼續使用已經失效的迭代器(程式可能會崩潰)
對于vector可能會導致其迭代器失效的操作有:
-
會引起其底層空間改變的操作,都有可能是迭代器失效,導致迭代器變成野指標,比如:resize、reserve、insert、assign、push_back等
#include <iostream> using namespace std; #include <vector> int main() { vector<int> v{1,2,3,4,5,6}; auto it = v.begin(); // 將有效元素個數增加到100個,多出的位置使用8填充,操作期間底層會擴容 // v.resize(100, 8); // reserve的作用就是改變擴容大小但不改變有效元素個數,操作期間可能會引起底層容量改變 // v.reserve(100); // 插入元素期間,可能會引起擴容,而導致原空間被釋放 // v.insert(v.begin(), 0); // v.push_back(8); // 給vector重新賦值,可能會引起底層容量改變 v.assign(100, 8); /* 出錯原因:以上操作,都有可能會導致vector擴容,也就是說vector底層原理舊空間被釋放掉, 而在列印時,it還使用的是釋放之間的舊空間,在對it迭代器操作時,實際操作的是一塊已經被釋放的 空間,而引起代碼運行時崩潰, 解決方式:在以上操作完成之后,如果想要繼續通過迭代器操作vector中的元素,只需給it重新 賦值即可, */ while(it != v.end()) { cout<< *it << " " ; ++it; } cout<<endl; return 0; } -
指定位置元素的洗掉操作–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所在位置的iterator vector<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就認為該位置迭代器失效了,
以下代碼的功能是洗掉vector中所有的偶數
#include <iostream> using namespace std; #include <vector> int main() { vector<int> v{ 1, 2, 3, 4 }; auto it = v.begin(); while (it != v.end()) { if (*it % 2 == 0) v.erase(it); ++it; } return 0; }看一下結果:
vs2019下:
g++(Linux)下:
可以看到兩個編譯器都對其報了錯誤,而且是與記憶體訪問相關的錯誤,為什么呢?
這里實際上就是一個迭代器失效的案例
解釋:
vector中有元素{1,2,3,4},1不是偶數,所以不會洗掉,迭代器it向后走,指向2,2是偶數,所以洗掉2,此時迭代器還是向后走,我們的原意是想讓it指向3,可是vector已經變成了{1,3,4},it指向的是第三個位置,所以指向了4,再洗掉4,vector變成了{1,3},it向后走,此時it已經不指向vector中的內容了,而v.end()指向的是3,所以it永遠不會等于v.end(),也就是it會一直向后非法訪問,直到訪問到沒有權限的位置,程式就例外結束了,
而vs是在洗掉2后,++it時出錯的,++it會出錯是因為VS編譯器會在++的時候對it進行檢查,如果有非法訪問的行為則直接拋例外
我們在vecotr中加一個數字5,結果就不一樣了:
vs下:
g++下:
可以看到g++下的編譯通過了,vs還是拋出了例外,因為這是一種巧合的情況,剛好不會發生非法的記憶體訪問,當洗掉4之后,it++指向了5,5不是偶數,于是不會被洗掉,it再++,it就到了v.end()的位置,結束回圈,
而vs中仍然在同樣的地方拋出了例外,是因為這種行為是不被允許的,可能會造成錯誤,于是vs就直接終止了程式,
那么怎么解決這種問題呢?
erase會回傳洗掉位置的下一個位置的迭代器,我們用it接收這個值,更新it的位置,指向的剛好就是下一個元素的位置,就不會發生非法的訪問了
//代碼int main() { vector<int> v{ 1, 2, 3, 4 }; auto it = v.begin(); while (it != v.end()) { if (*it % 2 == 0) it = v.erase(it); else ++it; } return 0; }
總結:
迭代器失效解決辦法:在使用前,對迭代器重新賦值即可
vector 在OJ中的使用
只出現一次的數字 - 力扣(LeetCode) (leetcode-cn.com)
楊輝三角 - 力扣(LeetCode) (leetcode-cn.com)
洗掉有序陣列中的重復項 - 力扣(LeetCode) (leetcode-cn.com)
只出現一次的數字 II - 力扣(LeetCode) (leetcode-cn.com)
只出現一次的數字 III - 力扣(LeetCode) (leetcode-cn.com)
陣列中出現次數超過一半的數字
電話號碼的字母組合 - 力扣(LeetCode) (leetcode-cn.com)
連續子陣列的最大和
vector深度剖析及模擬實作

start、finish和end_of_storage是vector的三個核心成員變數,這三個成員變數的意義如上圖所示,他們的型別是迭代器
template<class T>
typedef T value_type;
typedef value_type* iterator;
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
模擬實作vector
#include<iostream>
#include<algorithm>
#include<assert.h>
#include<string>
namespace ysj
{
template <class T>
class vector {
public:
typedef T value_type;
typedef value_type* iterator;
typedef const value_type* const_iterator;
//構造
vector()
:_start(nullptr)
, _finish(nullptr)
, _endof_storage(nullptr)
{}
vector(int n, const T& val = T())
:_start(nullptr)
, _finish(nullptr)
, _endof_storage(nullptr)
{
reserve(n);
while (n--)
push_back(val);
}
//迭代器構造
template<class InputIterator>
vector(InputIterator first, InputIterator last)
:_start(nullptr)
,_finish(nullptr)
,_endof_storage(nullptr)
{
reserve(last - first);
while (first != last)
{
push_back(*first);
++first;
}
}
//拷貝構造
vector(const vector& v)
:_start(nullptr)
,_finish(nullptr)
,_endof_storage(nullptr)
{
reserve(v.capacity());
iterator it = v. begin();
while (it != v.end())
{
push_back(*it);
++it;
}
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endof_storage, v._endof_storage);
}
//賦值多載
//傳統寫法
/*const vector<T>& operator=(const vector<T>& v)
{
delete[] _start;
_start = new T[v.capacity()];
memcpy(_start, v._start, v.size()*sizeof(T));
_finish = _start + v.size();
_endof_storage = _start + v.capacity();
return *this;
}*/
//現代寫法
const vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
size_t size()const
{
return _finish - _start;
}
size_t capacity()const
{
return _endof_storage - _start;
}
bool empty()
{
return _start == _finish;
}
//增容
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)//當前vector不為空
{
for (size_t i = 0; i < size(); ++i)
{
tmp[i] = _start[i];
}
//不能用memcpy拷貝,memcpy是位元組拷貝,屬于淺拷貝,如果vector裝的是string這樣需要深拷貝的成員,就會生成野指標,也就是string的_str指向了一塊被釋放的空間(下面的_start被釋放了)
/*memcpy(tmp, _start, sz * sizeof(T));*/
delete[] _start;
}
_start = tmp;
_finish = _start + sz;//用提前保存的sz而不是size介面,如果原vector是空的話,size()就是一個很大的值,就會造成非法訪問
_endof_storage = _start + n;
}
}
void resize(size_t n, T val = T())
{
//判斷增容
if (_finish == _endof_storage)
{
int newcapacity = 0 ? 4 : 2 * capacity();
resize(newcapacity);
}
//n<size就類似洗掉資料
if (n < size())
{
_finish = _start + n;
}
else
{
//小于capacity
if (n < capacity())
{
while (n >= size())
{
*_finish = val;
_finish++;
}
}
else//大于capacity
{
//增容
reserve(n);
while (n >= size())
{
*_finish = val;
_finish++;
}
}
}
}
//尾插
void push_back(const T& x)
{
//判斷增容
while (_finish == _endof_storage)
{
reserve(capacity() == 0 ? 4 : 2 * capacity());
}
*_finish = x;
++_finish;
}
//插入
iterator insert(iterator pos, T val)
{
//判斷增容
if (_finish == _endof_storage)
{
//增容會有迭代器失效的隱患,所以要記錄pos的相對位置
int len = pos - _start;
int newcapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newcapacity);
pos = _start + len;
}
iterator it = _finish;
while (it > pos)
{
*it = *(it - 1);
--it;
}
*pos = val;
_finish++;
return pos + 1;
}
iterator erase(iterator pos)
{
assert(!empty());
iterator it = pos;
while (it < _finish - 1)
{
*it = *(it + 1);
++it;
}
_finish--;
return pos;
}
void pop_back()
{
assert(!empty());
--_finish;
}
//迭代器
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
//const迭代器
iterator begin()const
{
return _start;
}
iterator end()const
{
return _finish;
}
//operator[]
T& operator[](size_t pos)
{
assert(pos < size());
return *(_start + pos);
}
void print()const
{
ysj::vector<T>::const_iterator it = begin();
while (it != end())
{
std::cout << *it << " ";
++it;
}
std::cout << std::endl;
}
~vector()
{
delete[] _start;
_start = _finish = _endof_storage = nullptr;
}
private:
iterator _start;
iterator _finish;
iterator _endof_storage;
};
}
使用memcpy拷貝問題
假設模擬實作的vector中的reserve介面中,使用memcpy進行的拷貝,以下代碼會發生什么問題?
int main()
{
ysj::vector<string> v;
v.push_back("1111");
v.push_back("2222");
v.push_back("3333");
return 0;
}
問題分析:
- memcpy是記憶體的二進制格式拷貝,將一段記憶體空間中內容原封不動的拷貝到另外一段記憶體空間中
- 如果拷貝的是自定義型別的元素,memcpy既高效又不會出錯,但如果拷貝的是自定義型別元素,并且
自定義型別元素中涉及到資源管理時,就會出錯,因為memcpy的拷貝實際是淺拷貝,

結論:如果物件中涉及到資源管理時,千萬不能使用memcpy進行物件之間的拷貝,因為memcpy是
淺拷貝,否則可能會引起記憶體泄漏甚至程式崩潰,
對vector核心介面的測驗
using namespace std;
// constructing vectors
void TestVector1()
{
// constructors used in the same order as described above:
ysj::vector<int> first; // empty vector of ints
ysj::vector<int> second(4, 100); // four ints with value 100
ysj::vector<int> third(second. begin(), second.end()); // iterating through second
ysj::vector<int> fourth(third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = { 16, 2, 77, 29 };
ysj::vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));
std::cout << "The contents of fifth are:";
for (ysj::vector<int>::iterator it = fifth. begin(); it != fifth.end(); ++it)
std::cout << *it << " ";
std::cout << endl;
// 測驗T是string時,拷貝問題
ysj::vector<string> strV;
strV.push_back("1111");
strV.push_back("2222");
strV.push_back("3333");
strV.push_back("4444");
for (size_t i = 0; i < strV.size(); ++i)
{
cout << strV[i] << " ";
}
cout << endl;
}
//vector iterator的使用
void PrintVector(const ysj::vector<int>& v)
{
// 使用const迭代器進行遍歷列印
ysj::vector<int>::const_iterator it = v. begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void TestVector2()
{
// 使用push_back插入4個資料
ysj::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
PrintVector(v);
// 使用迭代器進行修改
auto it = v. begin();
while (it != v.end())
{
*it *= 2;
++it;
}
PrintVector(v);
// 這里可以看出C++11支持iterator及介面,就支持范圍for
for (auto e : v)
cout << e << " ";
}
// find / insert / erase
void TestVector3()
{
int a[] = { 1, 2, 3, 4 };
ysj::vector<int> v(a, a + sizeof(a) / sizeof(a[0]));
// 使用find查找3所在位置的iterator
auto pos = find(v. begin(), v.end(), 3);
// 在pos位置之前插入30
v.insert(pos, 30);
PrintVector(v);
// 洗掉pos位置的資料
pos = find(v. begin(), v.end(), 3);
v.erase(pos);
PrintVector(v);
}
// iterator失效問題
void TestVector4()
{
int a[] = { 1, 2, 3, 4 };
ysj::vector<int> v(a, a + sizeof(a) / sizeof(a[0]));
// 洗掉pos位置的資料,導致pos迭代器失效
auto pos = find(v. begin(), v.end(), 3);
v.erase(pos);
cout << *pos << endl; // 此處會導致非法訪問
// 在pos位置插入資料,導致pos迭代器失效,
// insert會導致迭代器失效,是因為insert可
// 能會導致增容,增容后pos還指向原來的空間,而原來的空間已經釋放了,
pos = find(v. begin(), v.end(), 3);
v.insert(pos, 30);
cout << *pos << endl; // 此處會導致非法訪問
// 實作洗掉v中的所有偶數
// 下面的程式會崩潰掉,如果是偶數,erase導致it失效
// 對失效的迭代器進行++it,會導致程式崩潰
auto it = v. begin();
/*while (it != v.end())
{
if (*it % 2 == 0)
v.erase(it);
++it;
}*/
// 以上程式要改成下面這樣,erase會回傳洗掉位置的下一個位置
cout << "洗掉前:";
PrintVector(v);
it = v. begin();
while (it != v.end())
{
if (*it % 2 == 0)
it = v.erase(it);
else
++it;
}
cout << "洗掉后:";
PrintVector(v);
}
int main()
{
//TestVector1();
//TestVector2();
//TestVector3();
TestVector4();
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/354801.html
標籤:其他
上一篇:Java基礎學習
下一篇:Linux磁盤管理(下)
