【C++】模拟实现Vector

一. 定义和成员变量

为了避免和标准库中的命名冲突, 在自己的命名空间中定义Vector.
私有成员也只需要三个指针: _start(起始位置), _finish(结束位置), _end_of_storage.
所以像 size(), capacity() 的函数直接使用指针相减即可.

namespace My_Vector
{
    template<class T>
    class vector
    {
    public:
        // Vector的迭代器也是一个原生指针
        typedef T* iterator;
        typedef const T* const_iterator;
        
        size_t size() const
        {
            return _finish - _start;
        }

        size_t capacity() const
        {
            return _end_of_storage - _start;
        }
        
	private:
        iterator _start = nullptr; 			// 指向有效数据的开始
        iterator _finish = nullptr; 		// 指向有效数据的尾
        iterator _end_of_storage = nullptr; // 指向存储容量的尾
    };
}

二. 迭代器

Vector 的迭代器是一个原生指针, 直接返回指针即可.

iterator begin()
{
    return _start;
}

iterator end()
{
    return _finish;
}

const_iterator begin() const
{
    return _start;
}

const_iterator end() const
{
    return _finish;
}

三. 默认成员函数

1. 构造函数

Vector 的无参构造函数这里在成员变量声明时给了缺省值, 所以不需要任何处理.

迭代器区间初始化直接将区间中的每个对象插入即可.

//无参构造函数
vector()
{}

//迭代器区间初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
    int sz = last - first;	//区间大小
    reserve(sz);			//reserve() 开辟空间
    while (first != last)	//插入数据
    {
        push_back(*first);
        ++first;
    }
}

2. 析构函数

直接释放空间, 置空指针即可.

~vector()
{
    delete[] _start;	//这里在 reserve() 中 new[] 开辟的空间, 所以 delete[] 释放
    _start = _finish = _end_of_storage = nullptr;
}

3. 拷贝构造

可以先开辟空间, 然后使用迭代器将每个对象插入; 也可以直接使用迭代器区间初始化.

vector(const vector<T>& v)
{
    /*
    reserve(v.capacity());			//reserve() 开辟空间
    for (const auto& e : v)			//插入数据
        push_back(e);
    */
    
    vector<T> tmp(v.begin(), v.end());	//使用迭代器区间初始化 临时对象 tmp
    swap(tmp);						//交换 tmp 对象和 this 对象的成员变量 的指针
}

4. 赋值重载

利用拷贝构造实现即可.

vector<T>& operator= (vector<T> v)	//使用拷贝构造初始化 临时对象 v
{
    swap(v);		//交换 v 临时对象和 *this 对象的成员变量
    return *this;
}

四. 其他成员函数

1. Vector 内置 swap

直接交换成员变量即可.

void swap(vector<T>& v)
{
    std::swap(_start, v._start);
    std::swap(_finish, v._finish);
    std::swap(_end_of_storage, v._end_of_storage);
}

2. operator[ ]

返回 解引用指针后的引用即可.

T& operator[](size_t pos)
{
    return *(_start + pos);
}

const T& operator[](size_t pos) const
{
    return *(_start + pos);
}

3. reserve()

若扩容后需要挪动数据, 由于 Vector 需要适应各种类型, 所以 T 可以是任何类型, 所以挪动数据时如果是自定义类型必须使用 = (赋值重载) 进行深拷贝(内置类型使用 = 无所谓).

void reserve(size_t n)
{
    if (n > capacity())				//检查是否需要扩容
    {
        size_t old_sz = size();		//保存旧数据的大小
        T* new_start = new T[n];	//开辟新空间

        if (_start)				
        {
            for (size_t 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;
    }
}

4. resize()

void resize(size_t n, const T& value = T())
{
    if (n > size())				//检查是否需要插入数据
    {
        reserve(n);				//这里没有判断是否需要扩容, reserve() 函数中会判断
        for (int i = size(); i < n; i++)	//插入数据
            push_back(value);
    }
    else
        _finish = _start + n;	//若不需要插入数据, 直接更改结束位置即可
}

5. insert()

iterator insert(iterator pos, const T& x)
{
    assert(pos >= _start && pos <= _finish);	//判断 pos 是否越界

    if (_finish == _end_of_storage)				//检查是否需要扩容
    {
        size_t sz = pos - _start;				//记录 pos 的位置
        reserve((capacity() == 0 ? 4 : capacity() * 2));	//reserve() 空间
        pos = _start + sz;						//更新 pos
    }
            
    iterator end = _finish;					
    while (end != pos)							//挪动数据
    {
        *end = *(end - 1);
        --end;
    }
    *pos = x;									//插入 x

    ++_finish;									//更新结束位置
    return pos;
}

6. erase()

iterator erase(iterator pos)
{
    assert(pos >= _start && pos < _finish);		//判断 pos 是否越界

    iterator it = pos+1;
    while (it != _finish)						//挪动数据
    {
        *(it-1) = *it;
        ++it;
    }

    --_finish;									//更新结束位置
    return pos;
}
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值