vector各种接口的模拟实现

写在前面:

        其实相比string,vector的接口就要简单许多而且更加规范清晰,但是这里也有我们需要注意的问题,一个是浅拷贝的问题,另一个就是迭代器失效

        首先是浅拷贝,这里最容易给自己挖坑的就是在reserve()函数的时候,直接用memcpy()去一个字节一个字节的拷贝,一但调用时使用的是自定义类型,就会因为浅拷贝崩溃(例如vector);其次是迭代器失效,一个是insert,一个是erase,insert之后,除非更新,应当认为迭代器已经失效,比如vs编译器会直接报错,再就是erase,也会出现相同的问题,不过不同点是,insert不一定会迭代器失效,但是erase在不同容器中几乎都会失效

目录

一、基本框架

二、各种构造函数与析构函数

三、增删查改与扩容


一、基本框架

namespace wjl
{
    template
    class vector
    {
    public:
        typedef T* iterator;
        typedef const T* const_iterator;

    private:
        iterator _start = nullptr;
        iterator _finish = nullptr;
        iterator _end_of_storage = nullptr;
        int capacity = _finish - _start;
    }
}

二、各种构造函数与析构函数

 //vector()
 //{
     //这里什么都不需要写,因为编译器一定会走初始化列表
     //而下面声明的地方我们又给了缺省值,所以已经完成了初始化列表的初始化
 //}

 //C++11 强制生成默认构造
 vector() = default;

 //只要写了任意的构造,就不会在生成拷贝构造
 vector(const vector& v)
 {
     reserve(v.size());
     for (auto& e : v)
     {
         push_back(e);
     }
 }

//输入一个数的和他的个数,将整个vector都用这个数填充
vector(int n, const T& val = T())
{
    reserve(n);
    while (n--)
    {
        push_back(val);
    }
}

~vector()
{
    if (_start)
    {
        delete[] _start;
        _start = _finish = _end_of_storage = nullptr;
    }
}

三、增删查改与扩容

void clear()
{
    _finish = _start; 
}


vector& operator= (const vector& v)
{
    clear();
    if (this != &v)
    {
        reserve(v.size());
        for (auto& e : v)
        {
            push_back(e);
        }
    }

    return *this;
}

//以下部分为现代写法,但是传统的可读性更好,选择哪种看个人需求
/*void swap(vector& v)
{
    std::swap(_start, v._start);
    std::swap(_finish, v._finish);
    std::swap(_end_of_storage, v._end_of_storage);
}*/

/*vector& operator= (vector v)
{
    swap(v);
    return *this;
}*/

iterator begin()
{
    return _start;
}

iterator end()
{
    return _finish;
}

const_iterator begin() const
{
    return _start;
}

const_iterator end() const//意味着传过来的是const对象
{
    return _finish;
}

//这里就是将size变为n,并将变动的空间变为给定的值
void resize(size_t n, T val = T())
{
    if (n < size())
    {
        _finish = _start + n;
    }
    else
    {
        reserve(n);
        while (_finish < _start + n)
        {
            *_finish = val;
            _finish++;
        }
    }
}

int size()const
{
    return _finish - _start;
}

int capacity()const
{
    return _end_of_storage - _start;
}

//这里是第一个要注意的点
void reserve(size_t n)
{
    if (n > capacity())
    {
        //其实这里就是要注意size的更新问题
        int old_size = size();
        T* tmp = new T[n];
        //memcpy(tmp, _start, size() * sizeof(T));
        for (int i = 0; i < size(); i++)
        {
            //这里调用的是string的赋值,完成了深拷贝
            //内置类型不要紧,但是一但用了自定义类型就会因为浅拷贝导致程序崩溃
            tmp[i] = _start[i];
        }
        delete[] _start;

        _start = tmp;
        _finish = _start + old_size;
        _end_of_storage = tmp + n;
    }
}

void push_back(const T& x)
{
    if (_finish != _end_of_storage)
    {
        *_finish = x;
        _finish++;
    }
    else
    {
        reserve(capacity() == 0 ? 4 : capacity() * 2);
        *_finish = x;
        _finish++;
    }
}

T& operator[](int i)
{
    assert(i < size());

    return _start[i];
}

const T& operator[](int i) const 
{
    assert(i < size());

    return _start[i];
}

bool empty()const
{
    return _start == _finish;
}

void pop_back()
{
    assert(!empty());
    --_finish;
}

iterator& erase(iterator pos)
{
    //进行这样的erase操作之后,vs也会认为pos已经失效
    assert(pos >= _start);
    assert(pos <= _finish);

    iterator it = pos + 1;
    while (it < end())
    {
        *(it - 1) = *(it);
        it++;
    }
    _finish--;

    return pos;
}

void insert(iterator pos, const T& x)
{
    assert(pos >= _start);
    assert(pos <= _finish);
    //迭代器失效——基本上所有容器都会有erase迭代器失效的问题,但是insert不一定
    // 1、类似野指针 —— 在扩容之后
    // 2、位置意义已经变了
    //但是vs编译器进行了强制检查,insert之后访问会直接报错
    if (_finish == _end_of_storage)
    {
        reserve(capacity() == 0 ? 4 : capacity() * 2);
    }
    iterator end = _finish - 1;
    while (end >= pos)
    {
        *(end + 1) = *end;
        end--;
    }
    *pos = x;
    _finish++;
}

你可能感兴趣的:(前端,c++,c语言,vector)