(第一步) STL: stl_vector容器简略版实现

本文详细介绍了如何从头实现一个简单的STL vector容器,包括构造函数、析构函数、迭代器、容量相关函数、访问元素、修改容器操作等功能。代码已添加详细注释,同时提供了测试代码以验证实现的正确性。学习过程中参考了CSDN上的相关资源,并提供了链接供进一步学习。
摘要由CSDN通过智能技术生成

 stl_vector容器

本文参考了这位大佬的github,直接先使用了它的基本头文件,在此基础上创建实现自己容器,反向理解底层代码

学习参考步骤:https://blog.csdn.net/weixin_43729695/article/details/102980558

  1. Alloc.h 分配内存,使用二级配置器,必需,有需要的可以先看,alloc解析

  2. TypeTraits.h 类型萃取,必需

  3. Construct.h 容器的构造和析构,必需,简单不解析

  4. Allocator.h alloc.h和construct.h的直接上级,封装函数,必需,简单不解析

  5. Itearator.h 迭代器,必需,提供迭代器的各种参数

  6. Functional.h 实现小于、等于等仿函数,这个可以以后拓展写

  7. Utility.h 算法中使用,实现pair,其他容器建立后,回头很简单不解析

  8. ReserveseIterator.h 反向迭代器

  9. Algorithm.h 经典算法,必需

  10. UninitializedFunctions.h 未定义的初始变量的初始化,必需,对底层内存变量的操作,也好理解

这十个文件也可以直接从这https://download.csdn.net/download/qq_38223012/20680865 下载

刚刚开始学习,就完成简单的构造、析构和一些常用的功能,实现一个简单的vector容器,也不用太复杂,简单实现就好

注意为了区别代码:自己写的命名空间改成了mySTL

工具:visual studio 2019

亲自手写过,并添加详细注释

主要完成int类型的功能,其他类型只完成基本创建, insert等自行添加

完整版:https://blog.csdn.net/qq_38223012/article/details/119463625

stl_vector.h

#pragma once
 #ifndef _STL_VECTOR_H_
 #define _STL_VECTOR_H_
 ​
 #include "../Includes/TypeTraits.h"
 #include "../Includes/Algorithm.h"
 ​
 #include "../Includes/Iterator.h"
 #include "../Includes/ReverseIterator.h"
 #include "../Includes/UninitializedFunctions.h"
 #include "../Includes/Allocator.h"
 ​
 ​
 namespace mySTL {
     template<class T, class alloc = allocator<T>>
     class vector {
     
     public:
         // vector的嵌套型别定义             
         typedef T   value_type;             // 元素类型
         typedef T* pointer;                 // 指针类型
         typedef T* iterator;                // vector是线性空间,所以iterator普通指针
         typedef T& reference;               // 重构相关的左引用,引用类型
         typedef size_t size_type;           // 用于指明数组长度,它必须是一个正数
         typedef ptrdiff_t difference_type;  // 应保证足以存放同一数组中两个指针之间的差距,它有可能是负数。
 ​
     private:
 ​
         iterator start;             //目前使用空间的开头
         iterator finish;            //目前使用空间的结尾
         iterator endOfStorage;      //目前可用空间的尾部
 ​
         typedef alloc dataAllocator;
         
     public:
         //构造函数                                              // 构造类型
         vector(): start(0), finish(0), endOfStorage(0){}        // vector<int> vec;
         //explicit防止类构造函数的隐式自动转换.                   //
         explicit vector(const size_type n);                     // vector<int> vec(10);
         vector(const size_type n, const value_type& val);       // vector<int> vec(10, 1);
 ​
 ​
         //析构函数
         ~vector();
 ​
 ​
     public:
         // 迭代器相关函数
         iterator begin() { return start; }
         iterator end() { return finish; }
 ​
         // 容量相关函数
         size_type size() const { return finish - start; }               
         size_type capacity() const { return endOfStorage - start; }     
         bool empty() const { return start == finish; }
         void resize(size_type n, value_type val = value_type());
 ​
         // 访问元素相关
         reference operator[](const size_type i) { return *(begin() + i); }
         reference front() { return *(begin()); }
         reference back() { return *(end() - 1); }
 ​
         // 修改容器相关的操作
         // 清空容器,销毁容器中的所有对象并使容器的size为0,但不回收容器已有的空间
         void clear();
         void push_back(const value_type& val);
         void pop_back();
         iterator erase(iterator position);
         iterator insert(iterator position, const value_type& val);
         void insert(iterator position, const size_type& n, const value_type& val);
         template <class InputIterator>
         void insert(iterator position, InputIterator first, InputIterator last);
 ​
 ​
         // 容器的空间配置器相关
         alloc get_allocator() { return dataAllocator; }
 ​
     private:
         void destroyAndDeallocate();                                        // 析构并释放空间
         void allocateAndFill(const size_type n, const value_type& val);     // 分配空间并填充数值val
         template<class InputIterator>
         void reallocateAndCopy(iterator position, InputIterator first, InputIterator last);
         void reallocateAndFill(iterator position, const size_type& n, const value_type& val);
         size_type getNewCapacity(size_type len)const;
 ​
         template<class InputIterator>                                       // 判断是否内存够用,重新分配内存为原来的2倍
         void insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type);
         template<class Integer>
         void insert_aux(iterator position, Integer n, const value_type& value, std::true_type);
                                                                             
                                                                             
                                                                             
     };
 ​
 ​
 ​
 }
 ​
 #include "../Detail/stl_vector.impl.h"  //存放实现函数的位置
 #endif

stl_vector.impl.h

#pragma once
 ​
 namespace mySTL {
     //***********************构造,析构相关***********************
     //构造函数  
     template<class T, class alloc>
     vector<T, alloc>::vector(const size_type n)
     {
         allocateAndFill(n, value_type());
     }
 ​
     template<class T, class alloc>
     vector<T, alloc>::vector(const size_type n, const value_type& val)
     {
         allocateAndFill(n, val);
     }
 ​
     
 ​
     //析构函数
     template<class T, class alloc>  
     vector<T, alloc>::~vector()
     {
         destroyAndDeallocate();
     }
 ​
     //*************和容器的容量相关******************************
     template<class T, class alloc>
     void vector<T, alloc>::resize(size_type n, value_type val)
     {
         if (n < size())
         {
             dataAllocator::destroy(start + n, finish);
             finish = start + n;
         }
         else if (n > size() && n <= capacity())
         {
             auto lengthOfInsert = n - size();
             //局部初始化,底层通过memset初始化,返回填充结束的尾部地址
             finish = mySTL::uninitialized_fill_n(finish, lengthOfInsert, val); 
         }
         else if (n > capacity())
         {
             auto lengthOfInsert = n - size();
             // 以上三步为走
             // 第一步,获取扩容大小,并返回扩容后总的大小,进行新的内存分配
             // 第二步,copy当前vector数据,填充到新地址中, end指向原理容量大小的位置,
             // 第三步,将扩充部分进行数据填充,end指向扩容后的尾部
             T* newStart = dataAllocator::allocate(getNewCapacity(lengthOfInsert));
             // 数据拷贝,底层通过memcopy实现,返回当前大小的尾部地址
             T* newFinish = mySTL::uninitialized_copy(begin(), end(), newStart);
             newFinish = mySTL::uninitialized_fill_n(newFinish, lengthOfInsert, val);
             
 ​
             destroyAndDeallocate();
 ​
             // 更新容器参数
             start = newStart;
             finish = newFinish;
             endOfStorage = start + n;
         }
     }
 ​
     //***************修改容器的相关操作**************************
     template<class T, class alloc>
     void vector<T, alloc>::clear()
     {
         dataAllocator::destroy(start, finish);
         finish = start;
     }
 ​
     template<class T, class alloc>
     void vector<T, alloc>::push_back(const value_type& val)
     {
         insert(end(), val);
     }
 ​
     template<class T, class alloc>
     void vector<T, alloc>::pop_back()
     {
         --finish;
         dataAllocator::destroy(finish);
     }
 ​
     // 清除某位置上元素
     template<class T, class alloc>
     typename vector<T, alloc>::iterator vector<T, alloc>::erase(iterator position)
     {
         iterator first = position, last = position + 1;
         //尾部残留对象数
         difference_type lenOfTail = end() - last;
         //删去的对象数目
         difference_type lenOfRemoved = last - first;
 ​
         finish = finish - lenOfRemoved;
         // 向前移动 lenOfRemoved距离
         for (; lenOfTail != 0; --lenOfTail)
         {
             auto temp = (last - lenOfRemoved);
             *temp = *(last++);
         }
 ​
         return position;
     }
 ​
     /********************* insert 函数实现解析 ************/
 ​
 ​
     template<class T, class alloc>
     typename vector<T, alloc>::iterator vector<T, alloc>::insert(iterator position, const value_type& val)
     {
         const auto index = position - begin();
         insert(position, 1, val);
 ​
         return begin() + index;
     }
 ​
     
 ​
     template<class T, class Alloc>
     template<class InputIterator>
     void vector<T, Alloc>::insert(iterator position, InputIterator first, InputIterator last) {
         insert_aux(position, first, last, typename std::is_integral<InputIterator>::type());
     }
 ​
     template<class T, class alloc>
     void vector<T, alloc>::insert(iterator position, const size_type& n, const value_type& val)
     {
         insert_aux(position, n, val, typename std::is_integral<size_type>::type());    // 判断是否int类型,是就实现插入,不是终止,因为没有写string类型的
     }
 ​
     template<class T, class alloc>
     template<class InputIterator>
     typename void vector<T, alloc>::insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type)
     {
         difference_type locationLeft = endOfStorage - finish; // the size of left storage
         difference_type locationNeed = distance(first, last);//last - first;
 ​
         if (locationLeft >= locationNeed) {
             if (finish - position > locationNeed) {
                 mySTL::uninitialized_copy(finish - locationNeed, finish, finish);
                 std::copy_backward(position, finish - locationNeed, finish);
                 std::copy(first, last, position);
             }
             else {
                 iterator temp = mySTL::uninitialized_copy(first + (finish - position), last, finish);
                 mySTL::uninitialized_copy(position, finish, temp);
                 std::copy(first, first + (finish - position), position);
             }
             finish += locationNeed;
         }
         else {
             reallocateAndCopy(position, first, last);
         }
     }
 ​
     template<class T, class alloc>
     template<class Integer>
     typename void vector<T, alloc>::insert_aux(iterator position, Integer n, const value_type& value, std::true_type)
     {
         //其作用是如果它的条件返回错误,则终止程序执行。
         assert(n != 0);
 ​
         difference_type locationLeft = endOfStorage - finish;   // 未使用空间大小
         difference_type locationNeed = n;
 ​
         if (locationLeft >= locationNeed)                       // 当前容器满足插入空间大小
         {
             auto tempPtr = end() - 1;
 ​
             for (; tempPtr - position >= 0; --tempPtr)
             {
                 // placement new,就是在指针p所指向的内存空间创建一个T1类型的对象,
                 // 但是对象的内容是从T2类型的对象转换过来的(调用了T1的构造函数,T1::T1(value))。
                 // 就是在已有空间的基础上重新调整分配的空间
                 construct(tempPtr + locationNeed, *tempPtr);    
             }
 ​
             mySTL::uninitialized_fill_n(position, n, value);
 ​
             finish += locationNeed;
         }
         else
         {
             reallocateAndFill(position, n, value);
         }
 ​
 ​
     }
 ​
     /********************* insert 函数解析结束 ************/
 ​
     // 容器的空间配置器相关
 ​
     /********************* 扩展内存大小, 并返回新的大小 ************/
     template<class T, class alloc>
     typename vector<T, alloc>::size_type vector<T, alloc>::getNewCapacity(size_type len)const{
         size_type oldCapacity = endOfStorage - start;  // 旧容器的容量
 ​
         auto res = mySTL::max(oldCapacity, len);        // 容器容量扩展量,选择大的
 ​
         // 新容器的容量
         // 如果未定义,则选择resize所定的,
         // 如果定义了,容量*2,或者更大容量 + len(此时len比旧容量大)
         size_type newCapacity = (oldCapacity != 0 ? (oldCapacity + res) : len); 
 ​
         return newCapacity;
     }
 ​
     template<class T, class alloc>
     void vector<T, alloc>::destroyAndDeallocate()
     {
         if (capacity() != 0)
         {
             // destory负责调用类型的析构函数,销毁相应内存上的内容(但销毁后内存地址仍保留)
             // deallocate负责释放内存,在此之前应调用destory销毁,将内存地址返回给系统
             dataAllocator::destroy(start, finish);
             dataAllocator::deallocate(start, capacity());
         }
     }
 ​
     template<class T, class alloc>
     typename void vector<T, alloc>::allocateAndFill(const size_type n, const value_type& val)
     {
         start = dataAllocator::allocate(n);
         mySTL::uninitialized_fill_n(start, n, val);
         finish = endOfStorage = start + n;
 ​
     }
 ​
     template<class T, class alloc>
     template<class InputIterator>
     void vector<T, alloc>::reallocateAndCopy(iterator position, InputIterator first, InputIterator last)
     {
         difference_type newCapacity = getNewCapacity(last - first);
 ​
         T* newStart = dataAllocator::allocate(newCapacity);
         T* newEndOfStorage = newStart + newCapacity;
         T* newFinish = mySTL::uninitialized_copy(begin(), position, newStart);
         newFinish = mySTL::uninitialized_copy(first, last, newFinish);
         newFinish = mySTL::uninitialized_copy(position, end(), newFinish);
 ​
         destroyAndDeallocate();
         start = newStart;
         finish = newFinish;
         endOfStorage = newEndOfStorage;
     }
 ​
     
 ​
     template<class T, class alloc>
     void vector<T, alloc>::reallocateAndFill(iterator position, const size_type& n, const value_type& val)
     {
         difference_type newCapcity = getNewCapacity(n);
 ​
         T* newStart = dataAllocator::allocate(newCapcity);
         T* newEndOfStorage = newStart + newCapcity;
         T* newFinish = mySTL::uninitialized_copy(begin(), position, newStart);
         newFinish = mySTL::uninitialized_fill_n(newFinish, n, val);
         newFinish = mySTL::uninitialized_copy(position, end(), newFinish);
 ​
         destroyAndDeallocate();
 ​
         start = newStart;
         finish = newFinish;
         endOfStorage = newEndOfStorage;
     }
 ​
 }

后续还有一些拷贝函数,算法之类的,可以自行添加

stl_vector_test.h

 #pragma once
 ​
 #include "../p2_STL_Source/stl_vector.h"
 ​
 #include <vector>
 ​
 #include <array>
 #include <cassert>
 #include<iostream>
 #include <iterator>
 #include <string>
 ​
 using namespace std;
 ​
 namespace mySTL {
     namespace vectorTest {
         template<class T>
         using stdVec = std::vector<T>; //取别名
 ​
         template<class T>
         using myVec = mySTL::vector<T>;
 ​
         void print(std::vector<int> &v);
         void myprint(mySTL::vector<int>& v);
         void test01();
         void test02();
         void test03();
         void test04();
         void test05();    // 未写测试代码
         void test06();    // 未写测试代码
     }
 }

stl_vector_test.cpp

#include "stl_vector_test.h"
 ​
 namespace mySTL {
     namespace vectorTest {
         void print(std::vector<int>& v)
         {
             for (int i = 0; i < v.size(); i++)
             {
                 cout << v[i] << " ";
             }
             cout << endl;
         }
         void myprint(mySTL::vector<int>& v)
         {
             for (int i = 0; i < v.size(); i++)
             {
                 cout << v[i] << " ";
             }
             cout << endl;
         }
 ​
         void test01()
         {
             stdVec<string> v1(10, "xfy");
             myVec<string> v2(10, "xfy");
 ​
 ​
             cout << v1[0] << endl;
             cout << v1.size()<< endl;
             cout << v1.capacity() << endl;
             cout << v2[0] << endl;
             cout << v2.size() << endl;
             cout << v2.capacity() << endl;
         }
 ​
         void test02()
         {
             stdVec<int> v1;
             myVec<int> v2;
             cout << v1.size() << endl;
             cout << v2.size() << endl;
 ​
             for (int i = 0; i < 10; i++)
             {
                 v1.push_back(i + 1);
                 v2.push_back(i + 1);
             }
 ​
             cout << v1.size() << endl;
             cout << v2.size() << endl;
 ​
             print(v1);
             myprint(v2);
 ​
             v1.pop_back();
             v1.pop_back();
 ​
             v2.pop_back();
             v2.pop_back();
 ​
             print(v1);
             myprint(v2);
 ​
 ​
             cout << v1.capacity() << endl;
             cout << v2.capacity() << endl;
 ​
             v1.resize(20);
             v2.resize(20);
 ​
             cout << v1.size() << endl;
             cout << v2.size() << endl;
             cout << v1.capacity() << endl;
             cout << v2.capacity() << endl;
 ​
         }
 ​
         void test03()
         {
             stdVec<int> v1;
             myVec<int> v2;
             cout << v1.size() << endl;
             cout << v2.size() << endl;
 ​
             for (int i = 0; i < 5; i++)
             {
                 v1.push_back(i + 1);
                 v2.push_back(i + 1);
             }
             print(v1);
             myprint(v2);
 ​
             cout << v1.front() <<" "<< v1.back() << endl;
             cout << v2.front() << " " << v2.back() << endl;
 ​
             cout << v1[2]<< endl;
             cout << v2[2]<< endl;
 ​
             v1.insert(v1.begin(), 11);
             v2.insert(v2.begin(), 11);
 ​
             v1.insert(v1.begin() + 2, 11);
             v2.insert(v2.begin() + 2, 11);
 ​
             v1.insert(v1.end(), 11);
             v2.insert(v2.end(), 11);
 ​
             print(v1);
             myprint(v2);
 ​
             v1.erase(v1.begin());
             v2.erase(v2.begin());
             v1.erase(v1.end() - 1);
             v2.erase(v2.end() - 1);
 ​
             print(v1);
             myprint(v2);
         }
 ​
         class testTemp
         {
         public:
             //testTemp();
             void setT(string name, int num)
             {
                 this->name = name;
                 this->num = num;
             }
 ​
             void print_to()
             {
                 cout << "nams: " << this->name << "  num: " << this->num << endl;
             }
         private:
             string name;
             int num;
         };
 ​
         void test04()
         {
             testTemp tt;
             tt.setT("san", 16);
 ​
             stdVec<testTemp> v1;
             myVec<testTemp> v2;
 ​
             v1.push_back(tt);
             v2.push_back(tt);
 ​
             v1.front().print_to();
             v2.front().print_to();
         }
 ​
         void test05()
         {
         }
 ​
         void test06()
         {
         }
     }
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值