目录
vector相关接口实现
使用memcpy拷贝问题
迭代器失效
引起失效的操作
指定位置元素的删除操作
编辑引起底层空间改变的操作
vector相关接口实现
template<typename T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
public:
vector()
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{}
~vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
size_t capacity()const
{
return _end_of_storage - _start;
}
const T& operator[](size_t pos) const
{
assert(pos < size());
return _start[pos];
}
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
size_t size() const
{
return _finish - _start;
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)
{
//memcpy(tmp, _start, sizeof(T) * sz);
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_end_of_storage = _start + n;
}
}
void push_back(const T& x)
{
assert(pos < size());
insert(_finish, x);
}
void pop_back()
{
assert(_finish - _start > 0);
--_finish;
}
void insert(iterator pos, const T& x)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _end_of_storage)
{
//这里pos的位置也要记得改变,否者pos可能会出现问题。
int len = pos - _start;
reserve(capacity() = 0 ? 4 : capacity() * 2);
pos = _len + _start;
}
iterator end = _finish + 1;
while (end >= pos)
{
*(end) = *(end - 1);
end--;
}
*end = x;
_finish++;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos <= _finish);
iterator end = pos;
whlie(end < _finish)
{
*(end) = *(end + 1);
end++;
}
_finish--;
}
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
使用memcpy拷贝问题
假设模拟实现的vector中的reserve接口中,使用memcpy进行的拷贝,以下代码会发生什么问题?
int main()
{
vector<string> v;
v.push_back("1111");
v.push_back("2222");
v.push_back("3333");
return 0;
}
问题分析:
- 1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
- 2. 如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
迭代器失效
迭代器失效实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间
迭代器失效有两种情况
- 意义改变
- 崩溃出现野指针
引起失效的操作
指定位置元素的删除操作
void test_vector4()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//1 2 3 4 5
vector<int>::iterator pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
v.insert(pos, 30);
}
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//1 2 30 3 4 5
//删掉3
v.erase(pos); //迭代器失效
//迭代器失效情况:1、pos的意义改变 2、可能会崩溃出现野指针
//这里是意义改变
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//1 2 30 4 5
}
引起底层空间改变的操作
例如:resize,reserve,insert,assign,push_back等
void test_vector5()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
//要求删除vector中所有偶数
vector<int>::iterator it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{//erase(it)以后it失效,不能++
it = v.erase(it);//erase返回删除位置it的下一个位置
}
else
it++;
}
}