手撕简易版的vector

说明:本文vector手撕仿照的是库函数实现,利用迭代器作为私有成员

private: typedef T* iterator;

iterator _start = nullptr;

iterator _finish = nullptr;

iterator _end_of_storage = nullptr;
(1)构造和析构

注: // 构造采用默认参数,强制编译器生成

cpp 复制代码
vector() = default;
        ~vector()
        {
            if (_start)
                delete[] _start;
            _start = _finish = _end_of_storage = nullptr;
            cout << "~vector()" << endl;
        }

(2)//拷贝构造和赋值重载

注: //拷贝构造直接尾插

//赋值重载直接现代写法

cpp 复制代码
vector(const vector<T>& v)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}
        void swap(vector<T> v)
        {
            std::swap(_start,v._start);
            std::swap(_finish,v._finish);
            std::swap(_end_of_storage,v._end_of_storage);
        }
        vector<T>&operator=(vector<T> v)
        {
            swap(v);
            return *this;
        }

(3)//有效长度和开辟的大小空间

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

const size_t capacity()const { return _end_of_storage - _start; }
(4)//范围for,实现迭代器

//这里使用T*充当迭代器,并不是所有的函数迭代器都是T*,迭代器可以屏蔽底层代码细节

cpp 复制代码
iterator begin() { return _start; }
        iterator end() { return _finish; }
        const iterator begin() const{return _start;}
		const iterator end() const {return _finish;}

(5)//插入和删除等相关函数

注: //库函数的参数为迭代器,因此会引入扩容和删除会引发迭代器失效问题,所以返回更新后的迭代器进行迭代器的更新

//扩容

//问题:

//(1)移动数据时,memcpy是浅拷贝,所以涉及到深拷贝的内容如vector<string>,析构原空间时会造成数据string的析构

//此时便会引发数据销毁等野指针问题

//(2)更新_finish时,由于_start已经指向新地方所以原size(_finish-_start)也会变化,所以要保存原数据的大小

cpp 复制代码
void reserve(size_t n)
        {
            if (n > capacity())
            {
                iterator tmp = new T[n];
                //保存原数据大小
                size_t oldsize = size();
                // memcpy(tmp,_start);
                for (int i = 0; i < oldsize; i++)
                {
                    tmp[i] = _start[i];
                }
                delete[] _start;
                _start = tmp;
                _finish = _start + oldsize;
                _end_of_storage = _start + n;
            }
        }
        iterator insert(iterator pos, const T& val)
        {
            assert(pos >= begin() && pos <= end());
            size_t n = pos - _start;
            if (_finish == _end_of_storage)
            {
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                pos = _start + n;
            }
            size_t end = size();
            while (end > n)
            {
                _start[end] = _start[end - 1];
                end--;
            }
            _start[n] = val;
            _finish++;
            return pos;
        }
        iterator erase(iterator pos)
        {
            assert(pos >= begin() && pos <= end());
            size_t end = pos - _start + 1;
            while (end < size())
            {
                _start[end - 1] = _start[end];
                end++;
            }
            _finish--;
            return pos;
        }
        void push_back(const T& val)
        {
            insert(end(), val);
        }
        void pop_back()
        {
            erase(end() - 1);
        }

(6)所有代码:

cpp 复制代码
#include <iostream>
#include <cassert>
using namespace std;

namespace Myvector
{
    // 仿照库函数实现简易版的vector,学习并理解其底层原理
    template <class T>
    class vector
    {
        typedef T* iterator;

    public:
        // 构造与析构
        // 构造采用默认参数,强制编译器生成
        vector() = default;
        ~vector()
        {
            if (_start)
                delete[] _start;
            _start = _finish = _end_of_storage = nullptr;
            cout << "~vector()" << endl;
        }

        //拷贝构造和赋值重载
        //拷贝构造直接尾插
        //赋值重载直接现代写法
        vector(const vector<T>& v)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}
        void swap(vector<T> v)
        {
            std::swap(_start,v._start);
            std::swap(_finish,v._finish);
            std::swap(_end_of_storage,v._end_of_storage);
        }
        vector<T>&operator=(vector<T> v)
        {
            swap(v);
            return *this;
        }
        //有效长度和开辟的大小空间
        const size_t size()const { return _finish - _start; }
        const size_t capacity()const { return _end_of_storage - _start; }

        //范围for,实现迭代器
        //这里使用T*充当迭代器,并不是所有的函数迭代器都是T*,迭代器可以屏蔽底层代码细节
        iterator begin() { return _start; }
        iterator end() { return _finish; }
        const iterator begin() const{return _start;}
		const iterator end() const {return _finish;}

        //插入和删除等相关函数
        //库函数的参数为迭代器,因此会引入扩容和删除会引发迭代器失效问题,所以返回更新后的迭代器进行迭代器的更新
        //扩容
        //问题:
        //(1)移动数据时,memcpy是浅拷贝,所以涉及到深拷贝的内容如vector<string>,析构原空间时会造成数据string的析构
        //此时便会引发数据销毁等野指针问题
        //(2)更新_finish时,由于_start已经指向新地方所以原size(_finish-_start)也会变化,所以要保存原数据的大小
        void reserve(size_t n)
        {
            if (n > capacity())
            {
                iterator tmp = new T[n];
                //保存原数据大小
                size_t oldsize = size();
                // memcpy(tmp,_start);
                for (int i = 0; i < oldsize; i++)
                {
                    tmp[i] = _start[i];
                }
                delete[] _start;
                _start = tmp;
                _finish = _start + oldsize;
                _end_of_storage = _start + n;
            }
        }
        iterator insert(iterator pos, const T& val)
        {
            assert(pos >= begin() && pos <= end());
            size_t n = pos - _start;
            if (_finish == _end_of_storage)
            {
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                pos = _start + n;
            }
            size_t end = size();
            while (end > n)
            {
                _start[end] = _start[end - 1];
                end--;
            }
            _start[n] = val;
            _finish++;
            return pos;
        }
        iterator erase(iterator pos)
        {
            assert(pos >= begin() && pos <= end());
            size_t end = pos - _start + 1;
            while (end < size())
            {
                _start[end - 1] = _start[end];
                end++;
            }
            _finish--;
            return pos;
        }
        void push_back(const T& val)
        {
            insert(end(), val);
        }
        void pop_back()
        {
            erase(end() - 1);
        }
    private:
        iterator _start = nullptr;
        iterator _finish = nullptr;
        iterator _end_of_storage = nullptr;
    };

};

int main()
{
    Myvector::vector<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);
    v1.push_back(6);
    for (auto& e : v1)
    {
        cout << e << " ";
    }
    cout << endl;
    v1.pop_back();
    v1.pop_back();
    v1.pop_back();
    v1.pop_back();
    for (auto& e : v1)
    {
        cout << e << " ";
    }
    cout << endl; 
    return 0;
}
相关推荐
水饺编程15 分钟前
第4章,[标签 Win32] :TextOut 测试案例2
c语言·c++·windows·visual studio
tianzhiyi1989sq30 分钟前
C++工具库之PugiXML使用指南
java·数据库·c++
tankeven43 分钟前
HJ98 喜欢切数组的红
c++·算法
adore.9681 小时前
2.22 oj基础92 93 94+U12
数据结构·c++·算法
消失的旧时光-19431 小时前
C++ 多线程与并发系统取向(四)—— std::condition_variable:线程协作与生产者消费者模型(类比 Java wait/notify)
开发语言·c++
精彩极了吧1 小时前
C++基础知识-(②)面向对象(上)
c++·类和对象·封装·this指针·类的默认成员函数·赋值运算符重载
三水彡彡彡彡1 小时前
深入理解指针:常量、函数与数组
c++·学习
你好!蒋韦杰-(烟雨平生)1 小时前
Opengl模拟水面
c++·游戏·3d
Rhystt1 小时前
代码随想录第二十六天|669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
数据结构·c++·算法·leetcode
不染尘.2 小时前
字符串哈希
开发语言·数据结构·c++·算法·哈希算法