当前位置:   article > 正文

<C++>vector及其模拟实现_1、实现一个vector类,可以保存多个int类型数据,要求如下: 1) 无参构造函数、有参

1、实现一个vector类,可以保存多个int类型数据,要求如下: 1) 无参构造函数、有参

目录

一、vector类

二、vector类成员 

 1.vector类对象构造

(1).无参的构造函数

(2)范围构造函数。

(3) 填充构造函数。

2.拷贝构造  

3.vector元素访问符

4.赋值运算符重载

5.vector迭代器

6.vector容量

(1)vector增容机制 

(2)reserve()和resize()

(3)size()、capacity()

(4)empty()

7.vetor尾插和尾删

8.vector在任意位置插入和删除

(2)删除 

9.find()

10.swap() 

三、迭代器失效问题

1. 会引起其底层空间改变的操作,都有可能是迭代器失效

2.如何解决迭代器失效


一、vector类

vecotr是可以改变大小的数组的序列容器,其特点有:

(1)vector采用连续空间来存储元素,可以使用下标访问vector元素,访问元素和数组一样方便。vector大小可以动态改变,而且会被容器自动处理,这一点数组无法做到。

(2)vector使用动态分配分配数组来存储元素,插入新元素时,vector数组为了增加存储空间,会分配一个新数组,再把所有元素全部移动到这个数组里,代价相对高一些。

(3)vector会分配额外的空间来满足可能的增长,因为分配的存储空间比实际需要的的存储空间更大。vector以动态增长的方式管理存储空间。

(4)vector在访问元素、末尾添加删除元素时很高效,在其他位置插入删除需要挪动元素,效率低。

二、vector类成员 

  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int> v;//构造一个没有元素的空容器
  7. vector<int> v1(3, 5);//构造一个有3个元素的容器,每个元素的值都为5
  8. vector<int> v2(v1.begin(),v1.end());// 使用迭代器区间初始化
  9. string s1("good morning");
  10. vector<char> v3(s1.begin() + 2, --s1.end()); // 使用一部分区间初始化
  11. vector<int> v4(v2);//以与v2相同的顺序及值拷贝构造一个容器
  12. //插入4个元素
  13. v.push_back(1);
  14. v.push_back(2);
  15. v.push_back(3);
  16. v.push_back(4);
  17. return 0;
  18. }

 1.vector类对象构造

  1. //构造空的vector
  2. explicit vector (const allocator_type& alloc = allocator_type());
  3. //构造一个vector,有n个元素,每个元素值为val
  4. explicit vector (size_type n, const value_type& val = value_type(),
  5. const allocator_type& alloc = allocator_type());
  6. //构造一个vector,值为InputIterator的first到last之间的元素
  7. template <class InputIterator>
  8. vector (InputIterator first, InputIterator last,
  9. const allocator_type& alloc = allocator_type());
  10. //使用x拷贝构造一个vector
  11. vector (const vector& x);

(1).无参的构造函数

说明:

我们使用vector<int>  a; 创建一个对象a时,编译器会调用其构造函数对该对象进行初始化,三个指针都指向同一块空间,此时空间中没有元素,因为我们要求的是_start指向第一个元素,_finish指向最后一个元素的后一位,而这里_start和_finish在同一个位置,那我们就认为容器中元素个数为0.(_endOfStorage指向空间的最后一位)

  1. vector()
  2. :_start(nullptr)
  3. ,_finish(nullptr)
  4. ,_endOfStorage(nullptr)
  5. {}

(2)范围构造函数。

说明:

函数模板InputIterator是输入迭代器类型,并且类型不确定,我们在创建的时候传入参数为一段空间的前闭后开的区间,因为我们无法知道这段空间是以什么类型存在的,所以使用函数模板的方式进行定义,当该构造函数被调用的时候,first就会变成实际对应的类型了

  1. template <class InputIterator>
  2. // 重新声明迭代器,迭代器区间[first,last)可以是任意容器的迭代器
  3. vector(InputIterator first, InputIterator last)
  4. :_start(nullptr)
  5. , _finish(nullptr)
  6. , _end_of_storage(nullptr)
  7. {
  8. while (first != last)
  9. {
  10. push_back(*first);
  11. ++first;
  12. }
  13. }

(3) 填充构造函数。

向容器中插入n个值为val的元素 

  1. vector(size_t n, const T& val = T())
  2. :_start(nullptr)
  3. , _finish(nullptr)
  4. , _end_of_storage(nullptr)
  5. {
  6. reverse(n);
  7. for (size_t i = 0; i < n; ++i)
  8. {
  9. push_back(val);
  10. }
  11. }
  12. vector(int n, const T& val = T())
  13. :_start(nullptr)
  14. , _finish(nullptr)
  15. , _end_of_storage(nullptr)
  16. {
  17. reverse(n);
  18. for (int i = 0; i < n; ++i)
  19. {
  20. push_back(val);
  21. }
  22. }

理论上将,提供了vector(size_t n, const T& value = T())之后 vector(int n, const T& value = T())就不需要提供了,但是对于: vector<int> v(10, 5);编译器在编译时,认为T已经被实例化为int,而10和5编译器会默认其为int类型就不会走vector(size_t n, const T& value = T())这个构造方法,最终选择的是:vector(InputIterator first, InputIterator last)因为编译器觉得区间构造两个参数类型一致,因此编译器就会将InputIterator实例化为int但是10和5根本不是一个区间,编译时就报错了故需要增加该构造方法 

2.拷贝构造  

  1. vector<string> v6;
  2. v6.push_back(string("delia"));
  3. vector<string> v7(v6);//用v6拷贝构造v7
  4. PrintVector(v7);// delia
  5. vector<double> v8(v5);//用v5拷贝构造v8

假如不写vector类的拷贝构造函数,那么编译器自动生成的默认拷贝构造函数只能完成浅拷贝,vector类的3个成员变量的类型都是T*,如果T是内置类型,那么拷贝OK;但如果T是自定义类型,那么拷贝对象和被拷贝对象指向同一块空间,后定义的先析构,这块空间会被释放两次,程序就会崩掉。

(1)传统写法

  1. // 拷贝传统写法
  2. vector(const vector<T>& v)
  3. {
  4. _start = new T[v.capacity()];
  5. //memcpy(_start, v._start, sizeof(T) * v.size());
  6. // 拷贝数据
  7. for (size_t i = 0; i < v.size(); ++i)
  8. {
  9. // 若这里是string对象,调用的是string的赋值重载,是深拷贝
  10. _start[i] = v._start[i];
  11. }
  12. _finish = _start + v.size();
  13. _end_of_storage = _start + v.capacity();
  14. }

为什么2.拷贝数据时不使用memcpy呢?

1. memcpy 是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
2. 如果拷贝的是自定义类型的元素, memcpy 既高效又不会出错,但如果拷贝的是自定义类型元素,并且 自定义类型元素中涉及到资源管理时,就会出错,因为memcpy 的拷贝实际是浅拷贝。

 如vector<string>:

注意: memcpy拷贝的元素为string对象,是自定义类型,拷贝时为浅拷贝,其中两块空间的string数据的_str会指向同一串字符串,在析构时,vector的每个元素析构两次,那么同一块空间会被释放两次,程序会崩。

 (2)现代的拷贝构造:开空间+逐个尾插

使用现代的拷贝构造时必须初始化,否则_start、_finish、_end_of_storage都是随机值,拷贝数据时可能会导致越界。如果T是自定义类型,那么会调用T的拷贝构造函数进行深拷贝

  1. vector(const vector<T>& v)
  2. :_start(nullptr)
  3. , _finish(nullptr)
  4. , _end_of_storage(nullptr)
  5. {
  6. reserve(v.capacity());//开与v一样大小的空间
  7. //逐个尾插数据
  8. for (auto& e: v)
  9. {
  10. push_back(e);
  11. }
  12. }

3.vector元素访问符

  1. reference operator[] (size_type n); //可读可写
  2. const_reference operator[] (size_type n) const;//只读

vector使用operator[ ]遍历元素,像数组一样:

  1. for (size_t i = 0; i < v.size(); i++)
  2. {
  3. cout << v[i] << " ";
  4. }
  5. cout << endl;

 模拟实现:

  1. T& operator[](size_t pos)
  2. {
  3. assert(pos < size());// 判断pos是否合法
  4. return _start[pos];
  5. }
  6. const T& operator[](size_t pos) const
  7. {
  8. assert(pos < size());
  9. return _start[pos];
  10. }

4.赋值运算符重载

(1)传统的赋值运算符重载 

  1. // 传统写法
  2. vector<T> operator=(vector<T> v)
  3. {
  4. if (this != &v)
  5. {
  6. //1.清理空间,让空间变干净
  7. delete[] _start;
  8. //2.申请空间
  9. _start = new T[v.capacity()];
  10. //3.拷贝数据
  11. for (size_t i = 0; i < v.size(); i++)
  12. {
  13. _start[i] = v._start[i];
  14. }
  15. //4.更新大小及容量
  16. _finish = _start + v.size();
  17. _end_of_storage = _start + v.capacity();
  18. }
  19. }

(2)现代的赋值运算符重载函数 

形参是实参的一份拷贝  所以在operator=就不需要检测是否给自己赋值了  就可以直接交换了

  1. void swap(vector<T>& v)
  2. {
  3. std::swap(_start, v._start);
  4. std::swap(_finish, v._finish);
  5. std::swap(_end_of_storage, v._end_of_storage);
  6. }
  7. // v1 = v2
  8. vector<T>& operator=(vector<T> v)// 形参是实参的一份拷贝
  9. {
  10. swap(v);// 直接交换*this和v的内容
  11. return *this;
  12. }

5.vector迭代器

迭代器是一种容器可以统一使用的遍历方式,因此vector也支持使用迭代器遍历 

  1. iterator begin(); //可读可写
  2. const_iterator begin() const;//只读
  3. iterator end(); //可读可写
  4. const_iterator end() const; //只读
  5. reverse_iterator rbegin(); //反向迭代器 可读可写
  6. const_reverse_iterator rbegin() const; //反向迭代器 只读
  7. reverse_iterator rbegin(); //反向迭代器 可读可写
  8. const_reverse_iterator rbegin() const; //反向迭代器 只读

 (1)迭代器

①可读可写

  1. vector<int>::iterator it = v.begin();//可读可写
  2. while (it != v.end())
  3. {
  4. *it += 2;
  5. cout << *it << " ";
  6. ++it;
  7. }
  8. cout << endl;

模拟实现: 

  1. iterator begin()
  2. {
  3. return _start;
  4. }
  5. iterator end()
  6. {
  7. return _finish;
  8. }

②只读

  1. vector<int>::const_iterator it = v.begin();//只读
  2. while (it != v.end())
  3. {
  4. cout << *it << " ";
  5. it++;
  6. }
  7. cout << endl;
  1. const_iterator begin() const
  2. {
  3. return _start;
  4. }
  5. const_iterator end() const
  6. {
  7. return _finish;
  8. }

(2)反向迭代器 

①可读可写 

  1. vector<int>::reverse_iterator rit = v.rbegin();//可读可写
  2. while (rit != v.rend())
  3. {
  4. *rit += 2;
  5. cout << *rit << " ";
  6. rit++;
  7. }
  8. cout << endl;

②只读 

  1. vector<int>::const_reverse_iterator rit = v.rbegin();//只读
  2. while (rit != v.rend())
  3. {
  4. cout << *rit << " ";
  5. rit++;
  6. }
  7. cout << endl;

6.vector容量

(1)vector增容机制 

在VS下执行这段代码: 

  1. void test_vector3()
  2. {
  3. size_t sz;
  4. std::vector<int> foo;
  5. sz = foo.capacity();
  6. std::cout << "making foo grow:\n";
  7. for (int i = 0; i < 100; i++)
  8. {
  9. foo.push_back(i);
  10. if (sz != foo.capacity())
  11. {
  12. sz = foo.capacity();
  13. std::cout << "capacity changed:" << sz << endl;
  14. }
  15. }
  16. }

  同样的代码在linux下运行,发现是2倍增容的:

 因此 ,在不同的编译器下增容机制不同。

(2)reserve()和resize()

  1. void reserve (size_type n);//开辟n个元素空间
  2. void resize (size_type n, value_type val = value_type());
  3. //开辟n个元素空间,并将每个元素默认初始化为val

如果加上reserve(),那么会提前知道要开多少空间,就提前开好了,避免后面再开空间 

  1. void test_vector3()
  2. {
  3. size_t sz;
  4. std::vector<int> foo;
  5. sz = foo.capacity();
  6. foo.reserve(100);
  7. std::cout << "making foo grow:\n";
  8. for (int i = 0; i < 100; i++)
  9. {
  10. foo.push_back(i);
  11. if (sz != foo.capacity())
  12. {
  13. sz = foo.capacity();
  14. std::cout << "capacity changed:" << sz << endl;
  15. }
  16. }
  17. }

监视如下代码发现,reserve()之后,capacity变了,但是size没变;resize()之后,capacity变了,size也变了,且每个元素都被默认赋值为0

  1. vector<int> v1;
  2. v1.reserve(10);
  3. vector<int> v2;
  4. v2.resize(10);

reserve() 

注意 : 将数据拷贝到新空间,仍然不能用memcpy函数,因为对于需要深拷贝的自定义类型,使用memcpy函数以后,新开辟空间里的元素和原空间里的元素所指向的内存空间是一样的,当旧空间被释放时,会调用自定义类型的析构函数,从而使得新开辟空间里的元素指向的内存空间也被释放掉了 

  1. void reverse(size_t n)
  2. {
  3. if (n > capacity())
  4. {
  5. size_t sz = size();// 提前把原空间大小记录下来
  6. T* tmp = new T[n];
  7. if (_start) // 旧空间不为空就拷贝
  8. {
  9. //memcpy(tmp, _start, sizeof(T) * size());
  10. // 拷贝数据
  11. for (size_t i = 0; i < n; ++i)
  12. {
  13. tmp[i] = _start[i];
  14. }
  15. delete[] _start;// 释放旧空间
  16. }
  17. // 更新成员变量
  18. _start = tmp;
  19. _finish = _start + sz;
  20. _end_of_storage = _start + n;
  21. }
  22. }

reszie()

(1). 当 n < size 时,直接将 _finish = _start + n (将有效数据长度缩小)即可
(2). 当 size < n <= capacity 时,我们将有效数据的长度增加到 n,增加出来的有效数据内容是val
(3). 当 n > capacity时,先调用上面的 reserve 函数进行增容,再将有效数据的长度增加到 n,增加出来的有效数据内容是val

  1. void resize(size_t n, const T& val = T())
  2. {
  3. // 1.如果n小于当前的size,则数据个数缩小到n,相当于是删除数据
  4. if (n <= size())
  5. {
  6. _finish = _start + n;
  7. }
  8. else
  9. {
  10. // 2.空间不够则增容
  11. if (n > capacity())
  12. reverse(n);
  13. //赋值
  14. while (_finish != _start + n)
  15. {
  16. *_finish = val;
  17. ++_finish;
  18. }
  19. }
  20. }

(3)size()、capacity()

 返回vector元素个数和容量

  1. size_type size() const;
  2. size_t size() const
  3. {
  4. return _finish - _start;
  5. }
  6. size_t capacity() const
  7. {
  8. return _end_of_storage - _start;
  9. }

求v5的size() 

  1. vector<int> v5;
  2. //插入4个元素
  3. v5.push_back(1.1);
  4. v5.push_back(2.2);
  5. v5.push_back(3.3);
  6. v5.push_back(4.4);
  7. cout << v5.size() << endl; //4

(4)empty()

判断vector是否为空,为空返回1,不为空返回0

  1. bool empty() const;
  2. bool empty()
  3. {
  4. return _finish == _start;
  5. }

判断v5是否为空 

cout << v5.empty() << endl; //0

7.vetor尾插和尾删

  1. void push_back (const value_type& val);//尾插元素
  2. void pop_back();//尾删元素

 向v5尾插元素和尾删元素

  1. v5.push_back(5.5);
  2. v5.pop_back();

模拟实现 

  1. void push_back(const T& x)
  2. {
  3. // 判断是否需要增容
  4. if (_finish == _end_of_storage)
  5. {
  6. reverse(capacity() == 0 ? 4 : capacity() * 2);
  7. }
  8. *_finish = x;// 插入元素
  9. ++_finish;// 更新位置
  10. }
  11. void pop_back()
  12. {
  13. assert(!empty());
  14. --_finish;// 直接更新大小
  15. }

8.vector在任意位置插入和删除

  1. iterator insert (iterator position, const value_type& val);//插入val到position位置
  2. void insert (iterator position, size_type n, const value_type& val);
  3. //将n个val插入到position位置
  4. template <class InputIterator>
  5. void insert (iterator position, InputIterator first, InputIterator last);
  6. //将值为InputIterator的first到last之间的元素插入到position位置
  1. vector<double> v5;
  2. //插入4个float元素
  3. v5.push_back(1.1);
  4. v5.push_back(2.2);
  5. v5.push_back(3.3);
  6. v5.push_back(4.4);
  7. v5.push_back(5.5);
  8. v5.insert(v5.end(), 6.6);//在v5末尾插入6.6
  9. PrintVector(v5);// 1.1 2.2 3.3 4.4 5.5 6.6
  10. v5.insert(v5.begin(), 2,0);//在v5开头插入2个0
  11. PrintVector(v5);// 0 0 1.1 2.2 3.3 4.4 5.5 6.6
  12. vector<double> v6;
  13. v6.push_back(7.7);
  14. v6.push_back(8.8);
  15. v5.insert(v5.begin(), v6.begin(),v6.end());//在v5开头插入v6
  16. PrintVector(v5);// 7.7 8.8 0 0 1.1 2.2 3.3 4.4 5.5 6.6
  1. iterator insert(iterator pos, const T& val)
  2. {
  3. assert(pos >= _start && pos <= _finish);
  4. // 空间不够先扩容
  5. if (_finish == _end_of_storage)
  6. {
  7. size_t len = pos - _start;// 相对距离
  8. reverse(capacity() == 0 ? 4 : capacity() * 2);
  9. // 插入数据需扩容时,_start已经不是原来的了,而是新开空间后的了,
  10. // 这时候pos和_start不是同一块空间的了,所以就需更新pos,解决pos失效的问题
  11. pos = _start + len;
  12. }
  13. // 挪动数据
  14. iterator end = _finish - 1;
  15. while (end >= pos)
  16. {
  17. *(end + 1) = *end;
  18. --end;
  19. }
  20. *pos = val;
  21. ++_finish;
  22. return pos;
  23. }

(2)删除 

  1. iterator erase (iterator position);//删除某一位置元素
  2. iterator erase (iterator first, iterator last);
  3. //删除迭代器first和last之间的元素
  4. v5.erase(v5.begin());//删除v5开头元素
  5. PrintVector(v5);// 8.8 0 0 1.1 2.2 3.3 4.4 5.5 6.6
  6. v5.erase(v5.begin(), v5.begin()+2);//从v5开头删除2个元素
  7. PrintVector(v5);// 0 1.1 2.2 3.3 4.4 5.5 6.6
  1. iterator erase(iterator pos)
  2. {
  3. assert(pos >= _start && pos < _finish);
  4. iterator start = pos + 1;
  5. while (start != _finish)
  6. {
  7. *(start - 1) = *start;
  8. ++start;
  9. }
  10. --_finish;
  11. return pos;
  12. }

insert()和erase()之后需要挪动元素,时间复杂度为O(N),效率较低,不推荐用insert()和erase()插入删除元素

9.find()

在迭代器区间内查找元素,find函数实现在algorithm中,可以给所有容器使用,因此要使用find函数,就要include<algorithm>

  1. template <class InputIterator, class T>
  2. InputIterator find (InputIterator first, InputIterator last, const T& val);
  3. //在InputIterator迭代器first和last区间内查找val元素的位置

注意:迭代器区间是左闭右开,因此能取到第一个位置,但取不到最后一个位置 

  1. vector<double>::iterator pos = find(v5.begin(), v5.begin() + 3, 1.1);
  2. //在第一个元素和第四个元素(左闭右开,不包含第四个元素)之间查找值为1.1的元素位置
  3. v5.erase(pos);//删除1.1位置的元素,即删除1.1
  4. PrintVector(v5);

10.swap() 

将this指针指向的对象的内容和x进行交换 

void swap (vector& x);
  1. vector<int> v1;
  2. v1.push_back(20);
  3. vector<int> v2(10,0);
  4. v1.swap(v2);//交换v1和v1的元素
  5. PrintVector(v1);// 0 0 0 0 0 0 0 0 0 0
  6. PrintVector(v2);// 20
  1. void swap(vector<T>& v)
  2. {
  3. std::swap(_start, v._start);
  4. std::swap(_finish, v._finish);
  5. std::swap(_end_of_storage, v._end_of_storage);
  6. }

vector自己实现了swap(),相比较,库里的swap需要3次深拷贝,代价比较高:

  1. template <class T> void swap (T& a, T& b);
  2. {
  3. T c(a); a=b; b=c;
  4. }

三、迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了 封装,比如: vector 的迭代器就是原生态指针 T* 。因此 迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃 ( 如果继续使用已经失效的迭代器, 程序可能会崩溃)
对于 vector 可能会导致其迭代器失效的操作有:

1. 会引起其底层空间改变的操作,都有可能是迭代器失效

比如:resizereserveinsertassign、 push_back等。

 (1)在v中插入元素1,2,3,4,5后,在3前面插入30
  1. vector<int> v;
  2. //插入6个int元素
  3. v.push_back(1);
  4. v.push_back(2);
  5. v.push_back(3);
  6. v.push_back(4);
  7. v.push_back(5);
  8. //在3的前面插入30
  9. vector<int>::iterator pos = find(v.begin(), v.end(), 3);//查找3的位置
  10. if (pos != v.end())
  11. {
  12. v.insert(pos, 30);
  13. }
  14. PrintVector(v);

但是当删除30时,执行如下代码,程序崩了

  1. v.erase(pos);
  2. PrintVector(v);

 

这是因为先查找3,找到后挪动3的位置及之后的数据,插入30,3已经挪走了,但pos还指向原来的位置,也就是现在30的位置。再erase的时候,pos失效了,因为pos的意义变了,不再指向3了,所以程序崩溃。

(2)如下代码当删除所有偶数时,程序会崩

  1. vector<int> v;
  2. v.push_back(1);
  3. v.push_back(2);
  4. v.push_back(3);
  5. v.push_back(4);
  6. v.push_back(5);
  7. v.push_back(6);
  8. //删除v中所有的偶数
  9. vector<int>::iterator it = v.begin();
  10. while (it != v.end())
  11. {
  12. if (*it % 2 == 0)
  13. {
  14. v.erase(it);
  15. }
  16. it++;
  17. }
  18. PrintVector(v);

 执行过程:end不固定,删除数据后,每次都会去重新拿取,end是最后一个数的下一个位置

 而且执行过程中,由于删除数据后,it++了,迭代器的意义变了,所以结果一定不正确。

迭代器失效有两种情况:

(1)pos意义变了,插入数据以后,pos不再指向3,而是指向30,导致erase(pos)没有达到删除3的目的,反而删除的是30

(2)程序可能崩溃,pos变成了野指针

2.如何解决迭代器失效

在使用迭代器之前,对迭代器重新赋值

对于(1)使用迭代器之前,对迭代器重新赋值

  1. vector<int> v;
  2. //插入6个int元素
  3. v.push_back(1);
  4. v.push_back(2);
  5. v.push_back(3);
  6. v.push_back(4);
  7. v.push_back(5);
  8. //在3的前面插入30
  9. vector<int>::iterator pos = find(v.begin(), v.end(), 3);
  10. if (pos != v.end())
  11. {
  12. v.insert(pos, 30);
  13. }
  14. PrintVector(v);
  15. //使用迭代器之前,对迭代器重新赋值
  16. pos = find(v.begin(), v.end(), 3);
  17. //然后再使用迭代器
  18. if (pos != v.end())
  19. {
  20. v.erase(pos);
  21. }
  22. PrintVector(v);

对于(2)每次使用迭代器之前,对迭代器重新赋值,当it为偶数的位置时,删除偶数后,it不用++ 

  1. vector<int> v;
  2. v.push_back(1);
  3. v.push_back(2);
  4. v.push_back(3);
  5. v.push_back(4);
  6. v.push_back(5);
  7. v.push_back(6);
  8. //删除v中所有的偶数
  9. vector<int>::iterator it = v.begin();
  10. while (it != v.end())
  11. {
  12. if (*it % 2 == 0)
  13. {
  14. //每次使用迭代器之前,对迭代器重新赋值
  15. it = v.erase(it);//删除偶数后,it不用++
  16. }
  17. else
  18. {
  19. it++;//奇数,it++
  20. }
  21. }
  22. PrintVector(v);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/452717
推荐阅读
相关标签
  

闽ICP备14008679号