3.赋值运算符重载
(1)传统的赋值运算符重载
1. vector<T> operator=(vector<T> v) 2. { 3. if (this != &v) 4. { 5. //1.清理空间,让空间变干净 6. delete[] _start; 7. 8. //2.申请空间 9. _start = new T[v.capacity()]; 10. 11. //3.拷贝数据 12. for (size_t i = 0; i < v.size(); i++) 13. { 14. _start[i] = v._start[i]; 15. } 16. 17. //4.更新大小及容量 18. _finish = _start + v.size(); 19. _end_of_storage = _start + v.capacity(); 20. } 21. }
(2)现代的赋值运算符重载函数
1. void swap(vector<T> v) 2. { 3. ::swap(_start, v._start); 4. ::swap(_finish, v._finish); 5. ::swap(_end_of_storage, v._end_of_storage); 6. } 7. 8. vector<T> operator=(vector<T> v) 9. { 10. swap(v);//直接交换*this和v的内容 11. return *this; 12. }
4.析构函数
1. ~vector() 2. { 3. if (_start) 4. { 5. delete[] _start;//释放空间 6. } 7. _start = _finish = _end_of_storage = nullptr;//置空 8. }
5.迭代器
(1)普通迭代器
1. iterator begin() 2. { 3. return _start; 4. } 5. 6. iterator end() 7. { 8. return _finish; 9. }
(2)const迭代器
1. const_iterator begin() const 2. { 3. return _start; 4. } 5. 6. const_iterator end() const 7. { 8. return _finish; 9. }
6.operator[ ]
1. //普通operator[] 2. T& operator[](size_t i) 3. { 4. assert(i < size());//断言i是否合法 5. return _start[i]; 6. } 7. 8. //const operator[] 9. const T& operator[](size_t i) const 10. { 11. assert(i < size()); 12. return _start[i]; 13. }
7.size( )
1. size_t size() const 2. { 3. return _finish - _start;//结束位置-起始位置 4. }
8.capacity( )
1. size_t capacity() const 2. { 3. return _end_of_storage - _start;//可用空间-起始位置 4. }
9.empty( )
1. bool empty() 2. { 3. return _start == _finish;//起始空间是否为结束空间 4. }
10.reserve( )
开空间,扩展_capacity,_size不变
(1)保存对象大小
(2)申请新空间
(3)拷贝字符串
(4)释放旧空间
(6)更新新空间的大小及容量
1. void reserve(size_t n) 2. { 3. size_t sz = size();//1.保存对象的大小 4. if (n > capacity()) 5. { 6. T* tmp = new T[n];//2.申请新空间 7. if (_start) 8. { 9. //3.拷贝数据,memcpy是浅拷贝,会把旧空间地址又拷贝过去,不能用memcpy 10. for (size_t i = 0; i < v.size(); i++) 11. { 12. _start[i] = v._start[i]; 13. } 14. delete[] _start;//4.释放旧空间 15. } 16. 17. _start = tmp;//5.指向新空间 18. 19. //6.更新新空间的大小及容量 20. _finish = _start + sz; 21. _end_of_storage = _start + capacity(); 22. } 23. }
11.resize( )
(1)当resize的大小比原来小,说明空间够,只需要修改大小即可
(2)当resize的大小比原来大,说明空间不够,同时也说明容量可能不够,要判断是否需要申请容量
1. void resize(size_t n, T val = T()) 2. { 3. //1.当resize的大小比原来小,说明空间够,只需要修改大小即可 4. if (n < size()) 5. { 6. _finish = _start + n; 7. } 8. //2.当resize的大小比原来大,空间不够 9. else 10. { 11. //是否需要扩容 12. if (n > capacity) 13. { 14. reserve(n); 15. } 16. 17. //赋值 18. while (_finish < _start + n) 19. { 20. *_finish = val; 21. _finish++; 22. } 23. } 24. }
12.push_back( )
尾插时,需要:
(1)判断增容
(2)赋值
(3)更新大小
1. void push_back(const T& x) 2. { 3. //1.判断是否需要增容 4. if (_finish == _end_of_storage) 5. { 6. size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2; 7. reserve(newCapacity); 8. } 9. 10. //2.赋值 11. *_finish = x; 12. 13. //3.更新大小 14. ++_finish; 15. }
13.pop_back( )
尾删:
(1)判空
(2)直接更新大小
1. void pop_back() 2. { 3. assert(!empty()); 4. _finish--; 5. }
14.insert( )
在固定位置插入元素,需要考虑迭代器失效的问题
(1)判断是否需要扩容+保存并更新迭代器(增容时就要先保存pos的位置,扩容后要更新迭代器)
(2) 挪数据
(3)插入数据
(4)更新pos位置
1. void insert(iterator& pos, const T& x) 2. { 3. //1.判断容量是否够用,增容+更新迭代器 4. if (_finish == _end_of_storage) 5. { 6. size_t len = pos - _start; 7. size_t newCapapcity = capacity()==0 ? 4 : capacity() * 2; 8. 9. //更新pos,解决增容后pos失效的问题 10. pos = _start + len; 11. } 12. 13. //2.pos位及之后的数据往后挪 14. iterator end = _finish - 1; 15. while (end >= pos) 16. { 17. *(end + 1) = *end; 18. end--; 19. } 20. 21. //3.插入数据 22. *pos = x; 23. _finish++; 24. 25. //4.由于pos位置的元素向后挪动了一位,pos也要向后挪动一位指向原来指向的元素的位置 26. pos = pos + 1; 27. }
15.erase( )
(1)将pos位置及之后的元素向后挪
(2)更新大小
1. iterator erase(iterator pos) 2. { 3. assert(pos); 4. //1.将pos位置及之后的元素向后挪 5. iterator it = pos + 1; 6. while (it < _finish) 7. { 8. *(it - 1) = *it; 9. it++; 10. } 11. 12. //2.更新大小 13. _finish--; 14. 15. return pos; 16. }