C++ vector
vector的介绍及使用
1.1vector的介绍
1 .vector是表示可变大小数组的序列容器。
2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
6. 与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。
1.2vector的使用
vector的文档:http://www.cplusplus.com/reference/vector/vector/.
1.2.1vector的定义
1.2.2vector的使用
1.2.3vector的空间增长问题
resize只负责开辟空间,如果确定知道需要用多少空间,reverse可以缓解vector增容的代价问题
resize开辟空间的同时还会初始化,影响size。
1.2.3vector的增删查改
1.2.4vector的迭代器失效问题
迭代器的主要作用是让算法不用关心底层的数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如,vector的迭代器就是原生态指针T*。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成程序崩溃。
对于可能造成迭代器失效的操作有
1.会引起底层空间改变的操作都有可能造成迭代器失效,比如:resize,reverse,insert,push_back,assign等等。
2.指定元素的删除操作-earse
earse删除pos位置元素后,pos元素之后的元素会往前搬移,没有导致底层空间的改变,理论上迭代器不会失效,但是,如果pos刚好是最后一个元素,删完之后刚好是end的位置,而end位置是没有元素的,那么pos就失效了,因此删除vector上任意一个元素时,vs就认为该位置的迭代器失效了。
迭代器失效的解决方法:在使用之前,对迭代器重新赋值即可。
总结
vector的常用接口更多是插入与遍历,遍历最好用数组ret[i]的形式进行访问,因为vector里边没有对<<的重载,所以无法直接进行打印,用数组的方式会更为方便。
vector的模拟实现
namespace bit
{
template<class _Ty>
class vector
{
public:
typedef _Ty* iterator;
typedef const _Ty* const_iterator;
typedef size_t size_type;
public:
vector() : _start(nullptr), _finish(nullptr),_end_of_storage(nullptr)
{}
vector(int n, const _Ty& value = _Ty())
: _start(nullptr), _finish(nullptr),
_end_of_storage(nullptr)
{
reserve(n);
while(n--)
push_back(value);
}
vector(const_iterator first, const_iterator last)
: _start(nullptr), _finish(nullptr),
_end_of_storage(nullptr)
{
reserve(last - first);
while(first != last)
push_back(*first++);
}
vector(const vector<_Ty> &v)
: _start(nullptr), _finish(nullptr),
_end_of_storage(nullptr)
{
reserve(v.capacity());
for(int i=0; i<v.size(); ++i)
_start[i] = v[i];
_finish = _start + v.size();
}
vector<_Ty>& operator=(const vector<_Ty> &v)
{
if(this != &v)
{
vector<_Ty> tmp = v;
swap(tmp);
}
return *this;
}
~vector()
{
if(_start)
{
delete []_start;
_start = _finish = _end_of_storage = nullptr;
}
}
public:
void push_back(const _Ty &x)
{
insert(end(), x);
}
void pop_back()
{
erase(end()-1);
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
public:
_Ty& operator[](size_t pos)
{
return _start[pos];
}
const _Ty& operator[](size_t pos)const
{
return _start[pos];
}
const _Ty& at(size_type pos) const
{
assert(pos>=0 && pos<size());
return _start[pos];
}
_Ty& at(size_type pos)
{
assert(pos>=0 && pos<size());
return _start[pos];
}
public:
iterator insert(iterator pos, const _Ty& x)
{
if(_finish == _end_of_storage)
{
size_t old_n = pos - _start;
size_t new_sz = capacity()==0 ? 1 : 2*capacity();
reserve(new_sz);
//重新更新迭代器 pos
pos = _start + old_n;
}
iterator cur = end();
while(cur != pos)
{
*cur = *(cur-1);
cur--;
}
*cur = x; //
_finish++;
return cur;
}
iterator erase(iterator pos)
{
assert(pos>=_start && pos<_finish);
iterator cur = pos;
while(pos < _finish)
{
*pos = *(pos+1);
pos++;
}
--_finish;
return cur;
}
void reserve(size_type n)
{
if(n > capacity())
{
size_t old_sz = size();
_Ty *new_start = new _Ty[n];
//memcpy(new_start, _start, sizeof(_Ty)*old_sz);
for(int i=0; i<old_sz; ++i)
{
new_start[i] = _start[i];
}
delete []_start;
_start = new_start;
_finish = _start + old_sz;
_end_of_storage = _start + n;
}
}
void resize(size_t n, const _Ty& value = _Ty())
{
if(n <= size())
{
_finish = _start + n;
return;
}
if(n > capacity())
{
reserve(n);
}
size_t offset = n - size();
while(offset--)
{
*_finish++ = value;
}
}
public:
size_t size()const
{
return _finish - _start;
}
size_t capacity()const
{
return _end_of_storage - _start;
}
bool empty()const
{
return size() == 0;
}
public:
void swap(vector& str)
{
std::swap(_start, str._start);
std::swap(_finish, str._finish);
std::swap(_end_of_storage, str._end_of_storage);
}
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
};