vector容器迭代器
vector容器迭代器类主要实现 operator*()
、operator!=()
以及 operator++()
的运算符
同时在全局实现获得首尾迭代器的 begin
和 end
函数
迭代器失效问题
-
erase(it)
删除元素之后的所有元素的迭代器失效[it + 1, end) -
insert(it, val)
插入元素之后位置的所有元素的迭代器失效 [it, end),若发生扩容,全部元素迭代器失效 -
不同容器的迭代器不能进行比较
迭代器失效处理
在迭代器类中添加一个指向所迭代的容器对象的指针
用链表组织已产生的迭代器对象,在发生pop_back
, insert
和 erase
操作时对指定的指针范围对应的迭代器进行失效处理,即将迭代器的容器对象指针置为nullptr
。
// 容器迭代器失效用到的类
// 用链表组织创建过的迭代器
struct Iterator_Base
{
Iterator_Base(iterator* c = nullptr, Iterator_Base* n = nullptr)
: _cur(c), _next(n) {}
iterator* _cur;
Iterator_Base* _next;
};
Iterator_Base _head;
迭代器构造时头插
class iterator
{
public:
friend class vector<T, Alloc>;
iterator(vector<T, Alloc>* pvec = nullptr, T* ptr = nullptr)
: _ptr(ptr)
, _pVec(pvec)
{
// 头插法
Iterator_Base* itb = new Iterator_Base(this, _pVec->_head._next);
// _head不存实际的迭代器信息只是便于使用
// 即带头节点的链表
_pVec->_head._next = itb;
}
private:
T* _ptr;
// 标识当前迭代器属于哪个容器对象
vector<T, Alloc>* _pVec;
};
迭代器失效处理如下
// 检查容器迭代器对应指针是否在(first, last]范围内
// 若在,则使对应迭代器失效
void verify(T* first, T* last)
{
Iterator_Base* pre = &this->_head;
Iterator_Base* it = this->_head._next;
while (it != nullptr)
{
// iterator* --- Iterator_Base::_cur
// Iterator_Base* --- Iterator_Base::_next
if (it->_cur->_ptr > first && it->_cur->_ptr <= last)
{
// 迭代器失效,把iterator持有的【所属容器】指针置为nullptr
it->_cur->_pVec = nullptr; // 迭代器失效操作
// 删除当前迭代器节点,继续判断后面的迭代器节点是否失效
pre->_next = it->_next;
delete it;
it = pre->_next;
}
else
{
pre = it;
it = it->_next;
}
}
}
带有迭代器以及失效处理的vector代码
#include <iostream>
using namespace std;
// 使用空间配置器将内存分配于对象构造分开
// template <class _Ty, class _Alloc = allocator<_Ty>>
// class vector
//容器的空间配置器allocator做4件事: 内存开辟/释放,对象构造/ 析构
template<typename T>
struct Allocator
{
T* allocate(size_t size) // 内存开辟
{
return (T*)malloc(sizeof(T) * size);
}
void deallocate(void* p) // 释放内存
{
free(p);
}
void construct(T* p, const T& val) // 对象构造
{
new (p) T(val); // placement new
}
void destroy(T* p) // 对象析构
{
p->~T();
}
};
template<typename T, typename Alloc = Allocator<T>>
class vector
{
public:
vector(int size = 10)
{
// 需要把内存开辟和对象构造分开处理
//_first = new T[size];
// 只分配空间
_first = _allocator.allocate(size);
_last = _first;
_end = _first + size;
}
~vector()
{
//delete[] _first;
// 析构容器的【有效元素】,然后释放_first指针指向的堆内存
for (T* p = _first; p != _last; ++p)
{
_allocator.destroy(_first); // 析构有效元素
}
_allocator.deallocate(_first); // 释放堆上的数组内存
_first = _last = _end = nullptr;
}
vector(const vector<T>& rhs)
{
int size = rhs.end - rhs._first;
// _first = new T[size];
_first = _allocator.allocate(size); // 先分配内存
int len = rhs._last - rhs._first;
for (int i = 0; i < len; ++i)
{
//_first[i] = rhs._first[i];
_allocator.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
}
vector<T>& operator=(const vector<T>& rhs)
{
// 防止自赋值
if (this == &rhs)
{
return *this;
}
// 析构原来对象
// delete[] _first;
// 把_first指向的【有效元素】给析构掉
for (T* p = _first; p != _last; ++p)
{
_allocator.destroy(p);
}
_allocator.deallocate(_first); // 内存释放
int size = rhs.end - rhs._first;
//_first = new T[size]; // 分配空间+创建对象,一步到位
_first = _allocator.allocate(size); // #1 分配空间
int len = rhs._last - rhs._first;
for (int i = 0; i < len; ++i)
{
// _first[i] = rhs._first[i];
// #2 构造对象
_allocator.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
}
void push_back(const T& val)
{
if (full())
{
expand();
}
//*_last++ = val;
_allocator.construct(_last, val);
_last++;
}
void pop_back()
{
if (empty())
{
return;
}
//--_last; // 这样既没析构也没释放空间
// 使指向(_last-1, _last]之间的迭代器失效
verify(_last - 1, _last);
--_last;
_allocator.destroy(_last); // 要析构一下
}
T back() const // 返回容器末尾的元素值
{
return *(_last - 1);
}
bool full() const { return _last == _end; }
bool empty() const { return _first == _last; }
// 当前元素个数
int size() const { return _last - _first; }
T& operator[](int index)
{
if (index < 0 || index >= size())
{
throw "OutOfRangeException";
}
return _first[index];
}
// 迭代器本质就是对指针的封装
class iterator
{
public:
friend class vector<T, Alloc>;
iterator(vector<T, Alloc>* pvec = nullptr, T* ptr = nullptr)
: _ptr(ptr)
, _pVec(pvec)
{
// 头插法
Iterator_Base* itb = new Iterator_Base(this, _pVec->_head._next);
// _head不存实际的迭代器信息只是便于使用
// 即带头节点的链表
_pVec->_head._next = itb;
}
bool operator!=(const iterator& it) const
{
// 检查是不是属于同一个容器
if (_pVec == nullptr || _pVec != it._pVec)
{
throw "iterator incompatable!";
}
return _ptr != it._ptr;
}
void operator++()
{
// 检查迭代器有效性
if (_pVec == nullptr)
{
throw "iterator invalid!";
}
_ptr++;
}
T& operator*()
{
if (_pVec == nullptr)
{
throw "iterator invalid!";
}
return *_ptr;
}
const T& operator*() const
{
if (_pVec == nullptr)
{
throw "iterator invalid!";
}
return *_ptr;
}
private:
T* _ptr;
// 标识当前迭代器属于哪个容器对象
vector<T, Alloc>* _pVec;
};
//
// 返回首元素迭代器
iterator begin() { return iterator(this, _first); }
// 返回尾后元素迭代器
iterator end() { return iterator(this, _last); }
// 检查容器迭代器对应指针是否在(first, last]范围内
// 若在,则使对应迭代器失效
void verify(T* first, T* last)
{
Iterator_Base* pre = &this->_head;
Iterator_Base* it = this->_head._next;
while (it != nullptr)
{
// iterator* --- Iterator_Base::_cur
// Iterator_Base* --- Iterator_Base::_next
if (it->_cur->_ptr > first && it->_cur->_ptr <= last)
{
// 迭代器失效,把iterator持有的容器指针置为nullptr
it->_cur->_pVec = nullptr; // 迭代器失效操作
// 删除当前迭代器节点,继续判断后面的迭代器节点是否失效
pre->_next = it->_next;
delete it;
it = pre->_next;
}
else
{
pre = it;
it = it->_next;
}
}
}
iterator insert(iterator it, const T& val)
{
// 在it位置插入元素,原来[it,end)的元素后移
// 返回指向插入元素的迭代器
// 1.不考虑扩容
// 2. 不考虑 it._ptr的指针合法性
verify(it._ptr - 1, _last); // (it._ptr - 1, _last]的迭代器都失效
T* p = _last;
//
while (p > it._ptr)
{
_allocator.construct(p, *(p - 1));
_allocator.destroy(p - 1);
p--;
}
_allocator.construct(p, val);
_last++;
return iterator(this, p);
}
iterator erase(iterator it)
{
// 删除it位置元素,原来[it + 1,end)的元素前移
// 返回指向删除元素的下一元素的迭代器
verify(it._ptr - 1, _last); // (it._ptr - 1, _last]的迭代器都失效
T* p = it._ptr;
while (p < _last - 1)
{
_allocator.destroy(p);
_allocator.construct(p, *(p + 1));
p++;
}
// 析构最后一个位置
_allocator.destroy(p);
_last--;
return iterator(this, it._ptr);
}
private:
// 底层使用动态分配的数组来实现
T* _first; // 指向数组起始位置
T* _last; // 指向数组中有效元素的尾后位置
T* _end; // 指向数组空间的尾后位置
Alloc _allocator; // 定义容器的空间配置器对象
// 容器迭代器失效用到的类
// 用链表组织创建过的迭代器
struct Iterator_Base
{
Iterator_Base(iterator* c = nullptr, Iterator_Base* n = nullptr)
: _cur(c), _next(n) {}
iterator* _cur;
Iterator_Base* _next;
};
Iterator_Base _head;
void expand() // 容器的二倍扩容
{
int size = _end - _first;
// T* ptmp = new T[size * 2];
T* ptmp = _allocator.allocate(size * 2);
for (int i = 0; i < size; ++i)
{
// ptmp[i] = _first[i];
_allocator.construct(ptmp + i, _first[i]);
}
//delete[] _first;
for (T* p = _first; p != _last; ++p)
{
_allocator.destroy(p);
}
_allocator.deallocate(_first);
_first = ptmp;
_last = _first + size;
_end = _first + 2 * size;
}
};
int main(void)
{
vector<int> vec(200);
for (int i = 0; i < 20; ++i)
{
vec.push_back(rand() % 100 + 1);
}
auto it = vec.begin();
#if 1 // 在偶数前插入一个小1的数
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
// insert返回指向插入元素的迭代器
it = vec.insert(it, *it - 1); // 更新迭代器
++it;
}
}
#else // 删除所有偶数
while (it != vec.end())
{
if (*it % 2 == 0)
{
// 若写为vec.erase(it)则下一轮会用到失效迭代器,抛异常
it = vec.erase(it); // 更新迭代器
}
else
{
++it;
}
}
#endif
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
return 0;
}