文章目录
一,vector的基本成员。
namespace yyy
{
template <class T>
class vector
{
public:
//vector的迭代器是原生指针。
typedef T* iterator;
typedef const T* const_iterator;
//............其他
private:
iterator _start;//指向数据块的开始
iterator _finish;//指向有效数据的尾
iterator _end_of_storage;//储存存储容量的尾
};
二,构造函数,析构函数。
1,无参构造
vector()
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
}
~vector()
{
delete[]_start;
_start = _finish = _end_of_storage = nullptr;
}
2,迭代器区间构造
template <class InputIterator>
vector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
while (first != last)
{
push_back(*first);
first++;
}
}
为什么还要重新声明迭代器呢?
如果用iterator ,会导致初始化的迭代区间只能是vector的迭代器,重新声明迭代器,可以使迭代区间接收任意类型的迭代器。
3,用n个val进行构造
理论上讲,提供了vector(size_t n, const T& value = T())之后就不需要提供vector(int n, const T& value = T()),但是对于vector 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根本不是一个区间,编译时就报错了,故需要增加vector(int n, const T& value = T())方法。
vector(size_t n, const T& val = T())
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n,const T& val=T())
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(n);
for(int i=0;i<n;i++)
{
push_back(val);
}
}
3,析构函数。
~vector()
{
delete[]_start;
_start = _finish = _end_of_storage = nullptr;
}
三,拷贝构造。
假设v1(v2),拷贝构造如果直接拷贝,会出现浅拷贝。那么该如何解决呢?
我们采用迭代器区间构造传入v2的迭代器区间构造一个temp对象,temp对象和v2指向不同的空间,但是数据完全一样,然后将temp和v1进行交换,这样v2的值都拷贝到v1,且不会发生浅拷贝。
void swap(vector<T>& t)
{
std::swap(_start, t._start);
std::swap(_finish, t._finish);
std::swap(_end_of_storage, t._end_of_storage);
}
//拷贝构造
vector(const vector<T>& t)
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{
vector<T>temp(t.begin(), t.end());
swap(temp);
}
四,赋值运算符重载。
//v1=v2
vector<T>& operator=(vector<T> t)//调用拷贝构造,t和v2拥有一样的数据,但指向不同的空间。
{
swap(t);//将t和v1交换,完成赋值。
return *this;
}
二,迭代器
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
五,reserve(),resize()。
reserve()的功能,扩容,分配n个元素的存储空间。
resize()的功能,如果n小于当前size,则删除数据到n。
如果n>capacity,则扩容+初始化。
如果n>size且n<=capacity,则初始化。
初始化时,如果提供值,就用这个值填入,如果没有提供,就调用T()的默认构造函数来填入,如果是int类型,就是0,如果是指针,就是空。
void reserve(size_t n)
{
if (n > capacity())
{
size_t si = size();
T* temp = new T[n];//开辟新空间
if (_start)
{
for (size_t i = 0; i < si; i++)
{
temp[i] = _start[i];
}
delete[]_start;//释放旧空间
}
_start = temp;
_finish = _start + si;
_end_of_storage = _start + n;
}
}
void resize(size_t n, const T& t = T())
{
if (n > capacity())
{
reserve(n);
}
if (n > size())
{
while (_finish < _start + n)
{
*_finish = t;
_finish++;
}
}
else {
_finish = _start + n;
}
}
六,尾插尾删。
push_back(const T& t),pop_back();
void push_back(const T& t)
{
if (_finish == _end_of_storage)
{
reserve(capacity()==0?4:capacity()*2);
}
*_finish = t;
_finish++;
}
void pop_back()
{
assert(_finish > _start);
_finish--;
}
七,任意位置插入和删除。
iterator insert(iterator pos, const T& t), iterator erase(iterator pos);
iterator insert(iterator pos, const T& t)
{
assert(pos >=_start);
assert(pos <=_finish);
if (_finish==_end_of_storage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
*pos = t;
_finish++;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
iterator begin = pos + 1;
while (begin < _finish)
{
*(begin - 1) = *begin;
begin++;
}
_finish--;
return pos;
}
七,其他函数。
size_t capacity () const
{
return _end_of_storage - _start;
}
size_t size()const
{
return _finish - _start;
}
T& operator [](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator [](size_t pos)const
{
assert(pos < size());
return _start[pos];
}