【C++数据结构】动态数组vector实现

实现的vector跟标准库有那么一点点不同:

1. 支持头部插入和删除,但头部无空位时插入失败

2. 不检查越界

3. resize后改变capacity,如果此时size大于capacity,则size = capacity,否则,size不变

 

本次实现也是练习而已,如有问题,欢迎指出!

编译环境:GCC 7.3、vs 2005

 

很久以前实现过一次,现在重新实现,当作练习,熟悉一下底层结构。

有什么问题,欢迎指出!

 

代码如下:

#ifndef __VECTOR_H__
#define __VECTOR_H__

#if __cplusplus >= 201103L
#include <type_traits> // std::forward  std::move  std::declval
#endif 

#include <string.h> // memcpy

#if __cplusplus >= 201103L
#define null nullptr
#else
#define null NULL
#endif 

template<typename _Tp>
class vector
{
public:
    typedef _Tp                value_type;
    typedef value_type &       reference;
    typedef const value_type & const_reference;
    typedef value_type*        iterator;
    typedef const value_type*  const_iterator;
    typedef unsigned long      size_type;

#if __cplusplus >= 201103L
    typedef value_type &&     rvalue_reference;
#endif 

public:
    vector()
#if __cplusplus >= 201103L
     : vector(1)
    { }
#else 
     : _M_data(null), _M_beg(0), _M_end(0), _M_capacity(1)
    { resize(1); }
#endif

    vector(size_type s)
     : _M_data(null), _M_beg(0), _M_end(0), _M_capacity(s)
    { resize(_M_capacity); }

#if __cplusplus >= 201103L
    vector(vector &&v)
     : _M_data(null), _M_beg(0), _M_end(0), _M_capacity(1)
    { swap(v); }
#endif 

    vector(const vector &v)
     : _M_data(null), _M_beg(0), _M_end(0), _M_capacity(1)
    { operator=(v); }

    ~vector()
    { 
        _M_destroy<iterator, value_type>(begin(), end());
        ::operator delete[](_M_data);
    }

    void swap(vector &v)
    {
        _M_swap<value_type *>(_M_data, v._M_data);
        _M_swap<size_type>(_M_beg, v._M_beg);
        _M_swap<size_type>(_M_end, v._M_end);
    }

    vector& operator=(const vector &v)
    {
        resize(v.size());
        memcpy(begin(), v.begin(), sizeof(value_type) * v.size());
        _M_end += v.size();
        return *this;
    }

    void resize(size_type s)
    {
        value_type *tmp = static_cast<value_type *>(::operator new[](sizeof(value_type) * s));
        memcpy(tmp, begin(), sizeof(value_type) * size());
        if(null != _M_data)
        { ::operator delete[](_M_data); }

        _M_data = tmp;
        _M_end = size();
        _M_beg = 0;
        _M_capacity = s;
    }

    void push_back(const_reference t)
    { 
#if __cplusplus >= 201103L 
        emplace_back(t);
#else 
        if(_M_end >= capacity())
        { resize(capacity() * 2); }
        ::new(&_M_data[_M_end++]) value_type(t);
#endif
    }

#if __cplusplus >= 201103L
    void push_back(rvalue_reference t)
    { 
        if(_M_end >= capacity())
        { resize(capacity() * 2); }
        ::new(&_M_data[_M_end++]) value_type(std::move(t));
    }
#endif

    bool push_front(const_reference t)
    {
#if __cplusplus >= 201103L 
        return emplace_front(t);
#else 
        if(_M_beg == 0)
        { return false; }
        ::new(&_M_data[--_M_beg]) value_type(t);
        return true;
#endif
    }

#if __cplusplus >= 201103L
    bool push_front(rvalue_reference t)
    { 
        if(_M_beg == 0)
        { return false; }
        ::new(&_M_data[--_M_beg]) value_type(std::move(t));
        return true;
    }
#endif

    void pop_front()
    { _M_data[_M_beg++].~value_type(); }

    void pop_back()
    { _M_data[_M_end--].~value_type(); }

    reference front()
    { return *begin(); }

    reference back()
    { return *(end() - 1); }

    size_type capacity() const 
    { return _M_capacity; }

    size_type size() const 
    { return _M_end - _M_beg; }

    bool empty() const
    { return size() == 0; }

    iterator begin()
    { return &_M_data[_M_beg]; }

    const_iterator begin() const 
    { return &_M_data[_M_beg]; }

    iterator end()
    { return &_M_data[_M_end]; }

    const_iterator end() const 
    { return &_M_data[_M_end]; }

    const_iterator cbegin() const 
    { return begin(); }

    const_iterator cend() const 
    { return end(); }

    reference operator[](size_type i)
    { return _M_data[i + _M_beg]; }

    const_reference operator[](size_type i) const 
    { return _M_data[i + _M_beg]; }

    reference at(size_type i)
    { return operator[](i); }

    const_reference at(size_type i) const 
    { return operator[](i); }

    void clear()
    {
        _M_destroy<iterator, value_type>(begin(), end());
        _M_beg = _M_end = 0;
    }

#if __cplusplus >= 201103L 
    template<typename ... Args>
    void emplace_back(Args && ...args)
    {
        if(size() >= capacity())
        { resize(capacity() * 2); }
        ::new(&_M_data[_M_end++]) value_type(std::forward<value_type>(args)...);
    }

    template<typename ... Args>
    bool emplace_front(Args && ...args)
    {
        if(_M_beg == 0)
        { return false; }
        ::new(&_M_data[--_M_beg]) value_type(std::forward<value_type>(args)...);
        return true;
    }
#endif

private:
#if __cplusplus >= 201103L
    template<typename __ForwardIterator, 
             typename __ValueType = decltype(*std::declval<__ForwardIterator>())>
#else 
    template<typename __ForwardIterator, typename __ValueType>
#endif
    void _M_destroy(__ForwardIterator b, __ForwardIterator e)
    {
        while(b != e)
        { b++->~__ValueType(); }
    }

    template<typename __Type>
    void _M_swap(__Type &t1, __Type &t2)
    {
        __Type tmp = t1;
        t1 = t2;
        t2 = tmp;
    }

private:
    value_type *_M_data;
    size_type _M_beg;
    size_type _M_end; // 不包含该位置
    size_type _M_capacity;
};


#endif // __VECTOR_H__

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数中按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。 设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数中按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值