手撕简易版的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;
}
相关推荐
watson_pillow17 小时前
c++ 协程的初步理解
开发语言·c++
故事和你9118 小时前
洛谷-算法1-2-排序2
开发语言·数据结构·c++·算法·动态规划·图论
Tanecious.20 小时前
蓝桥杯备赛:Day6-B-小紫的劣势博弈 (牛客周赛 Round 85)
c++·蓝桥杯
流云鹤20 小时前
Codeforces Round 1090 (Div. 4)
c++·算法
小菜鸡桃蛋狗20 小时前
C++——string(上)
开发语言·c++
wljy120 小时前
第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(个人见解,已完结)
c语言·c++·算法·蓝桥杯·stl
清空mega21 小时前
C++中关于数学的一些语法回忆(2)
开发语言·c++·算法
想唱rap21 小时前
线程池以及读写问题
服务器·数据库·c++·mysql·ubuntu
望眼欲穿的程序猿21 小时前
Vscode Clangd 无法索引 C++17 或者以上标准
java·c++·vscode
6Hzlia1 天前
【Hot 100 刷题计划】 LeetCode 42. 接雨水 | C++ 动态规划与双指针题解
c++·算法·leetcode