在另一篇博客中我已经写了:vector容器介绍和使用以及迭代器失效问题,那么在这篇博客中我将要模拟实现一个简单的vector,对vector实现基本的增、删、改。
下图是vector的基本结构:
#pragma once
#include
#include
namespace Myvector{
template<class T>
class vector {
public:
//因为vector的底层是连续的,所以可以使用原生指针来当作迭代器使用
typedef T* iterator;
typedef const T* const_iterator; //const引用const迭代器
iterator begin() {
return _start;
}
iterator end() {
return _finish;
}
const_iterator begin() const{
return _start;
}
const_iterator end() const{
return _finish;
}
//当前vector元素的有效个数
size_t size(){
return _finish - _start;
}
//当前vector容器的个数
size_t capacity() {
return end_of_storage - _start;
}
//构造函数,构造一个空的vector
vector():
_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
{
}
//vector的析构函数
~vector() {
delete[]_start;
_start = _finish = end_of_storage = nullptr;
}
private:
iterator _start;
iterator _finish;
iterator end_of_storage;
}
}
void check_capacity() {
if (_finish == end_of_storage) {
size_t newcapacity = capacity() == 0 ? 1 : 2 * capacity();//当最初的时候,容量为0,要给个初始值
reserve(newcapacity);
}
}
void reserve(size_t n) {
if (n > capacity()) {
size_t sz = size(); //保存原有vector的大小
T* tmp = new T[n]; //重新配置新空间
// memcpy(tmp,_start,sizeof(T)*size()); 出现深浅拷贝问题
for(size_t i=0;i<sz;i++){
tmp[i] = _start[i];
}
delete[] _start; //释放原空间
//将vector的指针指向新配置的空间
_start = tmp;
_finish = _start + sz;
end_of_storage = _start + n;
}
}
int main()
{
Myvector::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 resize(size_t n,const T& val=T()) {
if(n>capacity()){
reserve(n); //第二种情况,要先进行扩容
}
if(n<size()){
//第一种情况,n
_finish=n+_start;
}else{
while(_finish!=_start+n){
*_finish=val;
++_finish;
}
}
}
void push_back(const T& val){
check_capacity();
*_finish=val;
++_finish;
}
iterator insert(iterator pos,const T& val){
assert(pos>=_start&&pos<=_finish); pos==_finish时在vector的末尾插入
size_t gap=pos-_start;//为了重新计算pos的位置,所以需要保存距离
check_capacity();
pos=_start+gap; //如果发生了扩容需要重新计算pos迭代器的位置
iterator end=_finish-1; //计算最后一个元素
while(end>=pos){
//将pos迭代器以及以后的元素依次往后移动
*(end+1)=*end;
--end;
}
*pos=val;
++_finish;
return pos;
}
iterator erase(iterator pos){
assert(pos>=_start&&pos<_finish); //pos不能等于_finish
iterator it=pos+1;
while(it!=_finish){
*(it-1)=*it;
--it;
}
--_finish;
return pos;
}
void pop_back(){
assert(_finish>_start);
--_finish;
}
T& operator[](size_t pos){
assert(pos<size());
return _start[pos];
}
void swap(vector<T> &v){
std::swap(_start,v._start);
std::swap(_finish,v._finish);
std::swap(end_of_storage,v.end_of_storage);
}
template<class InputIterator>
vector(InputIterator first,InputIterator last)
:_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
{
reserve(last - first);
while(first!=last){
push_back(*first);
++first;
}
}
vector<T>& operator=(vector<T> v){
//现代写法
swap(v);
return *this;
}
vector(const vector<T> &val)
:_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
{
vector<T> tmp(val.begin(),val.end());
swap(tmp);
}
#pragma once
#include
namespace Myvector {
template<class T>
class vector {
public:
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;
}
size_t size(){
return _finish - _start;
}
size_t capacity() {
return end_of_storage - _start;
}
vector():
_start(nullptr),
_finish(nullptr),
end_of_storage(nullptr)
{
}
void swap(vector<T> &v) {
std::swap(_start,v._start);
std::swap(_finish, v._finish);
std::swap(end_of_storage, v.end_of_storage);
}
template<class InputIterator>
vector(InputIterator first, InputIterator last) :
_start(nullptr), _finish(nullptr), end_of_storage(nullptr)
{
reserve(last - first);
while (first != last) {
push_back(*first);
++first;
}
}
vector(const vector<T>& val) :
_start(nullptr), _finish(nullptr), end_of_storage(nullptr)
{
vector<T> tmp(val.begin(), val.end());
swap(tmp);
}
vector<T>& operator=(vector<T> v) {
swap(v);
return *this;
}
~vector() {
delete[]_start;
_start = _finish = end_of_storage = nullptr;
}
void resize(size_t n,const T& val=T()) {
if (n > capacity()) {
reserve(n);
}
if (n<size()) {
_finish = _start+n;
}
else {
while (_finish != _start + n) {
*_finish = val;
++_finish;
}
}
}
void reserve(size_t n) {
if (n > capacity()) {
size_t sz = size();
T* tmp = new T[n];
//memcpy(tmp,_start,sizeof(T)*size()); //出现深浅拷贝问题
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 check_capacity() {
if (_finish == end_of_storage) {
size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newcapacity);
}
}
void push_back(const T&val) {
check_capacity();
*_finish = val;
++_finish;
}
iterator insert(iterator pos,const T& val) {
assert(pos>=_start&&_finish>=pos);
size_t posi = pos - _start;
check_capacity();
pos = _start + posi;
iterator end = _finish;
while (end >= pos) {
*(end + 1) = *end;
--end;
}
*pos = val;
++_finish;
return pos;
}
void pop_back() {
assert(_finish > _start);
--_finish;
}
iterator erase(iterator pos) {
assert(pos>=_start&&pos<_finish);
iterator it = pos + 1;
while (it != _finish) {
*(it - 1) = *it;
++it;
}
--_finish;
return pos;
}
T& operator[](size_t pos) {
assert(pos < size());
return _start[pos];
}
private:
iterator _start;
iterator _finish;
iterator end_of_storage;
};
}