容量和大小相关函数:
size和capacity
reserve
resize
empty和clear
修改容器内容相关函数:
push_back
pop_back
insert
erase
swap
访问容器相关函数:
operator[ ]
vector模拟实现整体代码
namespace wjq
{
template
class vector
{
public:
//构造函数
vector();
vector(size_t n, const T& val = T());
vector(int n, const T& val = T());
template
vector(InputIterator first, InputIterator last);
//拷贝构造
void swap(vector& v);
vector(const vector& v);
//赋值运算符重载
vector& operator=(vector v);
//析构函数
~vector();
//迭代器
typedef T* iterator;
iterator begin();
iterator end();
const iterator begin()const;
const iterator end()const;
//访问容器相关函数
T& operator[](size_t pos);
const T& operator[](size_t pos)const;
//reserve接口
void reserve(size_t n);
//resize接口
void resize(size_t n, T val = T());
//push_back/pop_back接口
void push_back(const T& val);
void pop_back();
//insert和erase接口
iterator insert(iterator pos, const T& val);
iterator erase(iterator pos);
//小接口
size_t size()const;
size_t capacity()const;
bool empty()const;
void clear();
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
}
vector()
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{}
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);
}
}
template
vector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
while (first != last)
{
push_back(*first);
++first;
}
}
~vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
传统写法:
vector(const vector& v)
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); ++i)
{
_start[i] = v[i];
}
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
}
注意:将容器当中的数据一个个拷贝过来时不能使用memcpy函数,当vector存储的数据是内置类型或无需进行深拷贝的自定义类型时,使用memcpy函数是没什么问题的,但当vector存储的数据是需要进行深拷贝的自定义类型时,使用memcpy函数的弊端就体现出来了,例如,当vector存储的是string类的时候:
并且vector当中存储的每一个string都指向自己所存储的字符串
如果此时我们使用的是memcpy函数进行拷贝构造的话,那么拷贝构造出来的vector当中存储的每个string的成员变量的值将与被拷贝的vector当中存储的每个string的成员变量的值相同,即两个vector当中的每个对应的string成员都指向同一个字符串空间.
这显然不是我们想得到的结果,那么所给代码是如何解决这个问题的呢?
代码中看似是使用普通的"="将容器当中的数据一个一个拷贝过来,实际上是调用了赋值运算符重载函数,而string类的赋值运算符重载是深拷贝,所以拷贝结果是这样的:
现代写法一:
vector(const vector& v)
: _start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(v.capacity());
for (const auto& e : v)
{
push_back(e);
}
}
现代写法二:
void swap(vector& v)//一定要加引用,不然拷贝构造函数调用swap会引发无限拷贝
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
vector(const vector& v)
: _start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
vector tmp(v.begin(), v.end());
swap(tmp);
}
传统写法:
vector& operator=(const vector& v)
{
if (this != &v)
{
delete[] _start;
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); ++i)
{
_start[i] = v[i];
}
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
return *this;
}
}
现代写法:
赋值运算符重载的参数传参并没有使用引用传参,因为这样可以直接调用vector的拷贝构造函数,然后将这个拷贝构造出来的容器v与其进行交换,此时就完成了赋值操作,而容器v在函数调用结束后时自动析构.
注意:赋值运算符重载的现代写法也是进行的深拷贝,只不过是调用的vector的拷贝构造函数进行的深拷贝,在赋值运算符重载函数当中仅仅是将深拷贝出来的对象与其进行了交换而已.
vector& operator=(vector v)//能解决自己给自己赋值的问题
{
swap(v);
return *this;
}
typedef T* iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const iterator begin()const
{
return _start;
}
const iterator end()const
{
return _finish;
}
size_t size()const
{
return _finish - _start;
}
size_t capacity()const
{
return _end_of_storage - _start;
}
void reserve(size_t n)
{
//扩容
if (n > capacity())
{
size_t oldSize = size();
T* tmp = new T[n];
if (_start != nullptr)
{
for (size_t i = 0; i < oldSize; ++i)
{
tmp[i] = _start[i];//调用赋值运算符重载完成深拷贝
}
delete[] _start;
}
_start = tmp;
_finish = _start + oldSize;
_end_of_storage = _start + n;
}
}
void resize(size_t n, T val = T())
{
if (n > capacity())
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else if (n > size())
{
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else
{
_finish = _start + n;
}
}
bool empty()const
{
return _start == _finish;
}
void clear()
{
_finish = _start;
}
void push_back(const T& val)
{
if (_finish == _end_of_storage)
{
size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newCapacity);
}
*_finish = val;
++_finish;
}
void pop_back()
{
assert(!empty());
--_finish;
}
iterator insert(iterator pos, const T& val)
{
assert(pos >= _start && pos < _finish);
//判断扩容
if (_finish == _end_of_storage)
{
size_t len = pos - _start;
size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newCapacity);
pos = _start + len;
}
//挪动数据
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
//填入数据
*pos = val;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
iterator begin = pos + 1;
while (begin < _finish)
{
*(begin - 1) = *begin;
++begin;
}
--_finish;
return pos;
}
void swap(vector& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
#pragma once
#include
#include
using std::cout;
using std::cin;
using std::endl;
namespace jly
{
template
class vector
{
public:
//构造函数
vector()
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{}
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())//多重载一个int版本的构造,解决调函数不明确的问题
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
reserve(n);
for (int i = 0; i < n; ++i)
{
push_back(val);
}
}
template
vector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
while (first != last)
{
push_back(*first++);
}
}
//拷贝构造
void swap(vector& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
vector(const vector& v)
: _start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
vector tmp(v.begin(), v.end());
swap(tmp);
}
//vector(const vector& v)//写法二
// : _start(nullptr)
// , _finish(nullptr)
// , _end_of_storage(nullptr)
//{
// reserve(v.capacity());
// for (const auto& e : v)
// {
// push_back(e);
// }
//}
//赋值运算符重载
vector& operator=(vector v)
{
swap(v);
return *this;
}
//析构函数
~vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
//迭代器
typedef T* iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const iterator begin()const
{
return _start;
}
const iterator end()const
{
return _finish;
}
T& operator[](size_t pos)
{
return _start[pos];
}
const T& operator[](size_t pos)const
{
return _start[pos];
}
//reserve接口
void reserve(size_t n)
{
//扩容
if (n > capacity())
{
size_t oldSize = size();
T* tmp = new T[n];
if (_start != nullptr)
{
//memcpy(tmp, _start, sizeof(T) * oldSize);
for (size_t i = 0; i < oldSize; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + oldSize;
_end_of_storage = _start + n;
}
}
//resize接口
void resize(size_t n, T val = T())
{
if (n > capacity())
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else if (n > size())
{
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else
{
_finish = _start + n;
}
}
//push_back/pop_back接口
void push_back(const T& val)
{
if (_finish == _end_of_storage)
{
size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newCapacity);
}
*_finish = val;
++_finish;
}
void pop_back()
{
assert(!empty());
--_finish;
}
//insert和erase接口
iterator insert(iterator pos, const T& val)
{
assert(pos >= _start && pos < _finish);
//判断扩容
if (_finish == _end_of_storage)
{
size_t len = pos - _start;
size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newCapacity);
pos = _start + len;
}
//挪动数据
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
//填入数据
*pos = val;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
iterator begin = pos + 1;
while (begin < _finish)
{
*(begin - 1) = *begin;
++begin;
}
--_finish;
return pos;
}
//小接口
size_t size()const
{
return _finish - _start;
}
size_t capacity()const
{
return _end_of_storage - _start;
}
bool empty()const
{
return _start == _finish;
}
void clear()
{
_finish = _start;
}
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
}