关于STL中vector的内存管理与简单代码实现

本文详细解析了C++ STL中Vector容器的内部实现原理,包括其内存管理机制、扩容策略及常用接口的实现方式。通过自定义Vector类并演示其使用过程,帮助读者掌握Vector的工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vector 的内部实现其实就是一块连续内存,它和传统的array不同的是支持扩容,不用考虑越界。vector的迭代器就是最简单的指向容器内类型的指针。其内部有三个指针,start(指向数据存储区的首地址),finish(已使用的数据区的尾端),end_of_storage(指向容量尾端,容量一般富余),当遇到满载的情况,finish指针和 end_of_storage 指针相等,也就是容量用完的时候,如果继续插入元素,就会扩容。

需要扩容的时候,空间适配器就会从新寻找一块更大的内存空间(因为vector内部是一块连续的内存),然后start指向新内存首地址,原始数据复制,新数据插入,同时更新finish以及end_of_storage即可。扩容的规模一般是原始容量的两倍。

下面的代码参照 侯捷《STL源码剖析》第四章。意在了解vector的内存管理以及各个接口的实现。出于简单考虑,部分接口没有按照标准做,空间适配器的部分是我自己手动实现的,也没有再做成公共接口,而是直接加在函数实现里面了,可能比较粗糙。



  1. #include<iostream>   
  2. using namespace std;  
  3.   
  4. template <class T>  
  5. class MyVector{  
  6. public:  
  7.       
  8.     typedef T * iterator;  
  9.     typedef T * pointer;  
  10.     typedef T & reference;  
  11.       
  12.     MyVector():start(0),finish(0),end_of_storage(0){}  
  13.     MyVector(int n,const reference val)//申请n单位空间,并用val初始化   
  14.     {  
  15.         start = new T[n];  
  16.         finish = start;  
  17.         end_of_storage = start + n;  
  18.         while(n--) { *finish++=val; }  
  19.     }  
  20.     MyVector(int n)//申请n单位空间,初始化为0   
  21.     {  
  22.         start = new T[n];  
  23.         finish = start;  
  24.         end_of_storage = start + n;  
  25.         while(n--) { *finish++=0; }  
  26.     }  
  27.       
  28.     ~MyVector(){  
  29.         iterator i;  
  30.         for(i=start;i<end_of_storage;i++) i->~T();  
  31.     }  
  32.       
  33.     iterator begin() const { return start; }  
  34.     iterator end() const { return finish; }  
  35.       
  36.     //注意size的定义,返回值是end - begin,也就是说,finish指向的是最后一个元素后面的一个地址   
  37.     int size() const { return int(end()-begin()); }  
  38.       
  39.     //void resize(int new_size,const reference x);//重新定义空间大小,而且完成初始化,finish指针在空间尾端   
  40.     //void resize(int new_size);   
  41.     //void reserve(int new_size);//重新定义空间大小,但是不改变finish指针   
  42.     int capacity() const { return end_of_storage-begin(); }  
  43.       
  44.     bool empty() const { return begin() == end(); }  
  45.       
  46.     reference operator[](int n) { return *(begin()+n); }  
  47.     reference front() { return *begin(); }  
  48.     reference back() { return *(end()-1); }  
  49.       
  50.       
  51.     void push_back(const reference x){  
  52.         if(finish != end_of_storage)//未满载   
  53.         {  
  54.             *finish = x;  
  55.             finish++;  
  56.         }  
  57.         else insert(end(),1,x);//满载,需要重新分配空间,并完成已有成员的搬移   
  58.     }  
  59.       
  60.     void pop_back()//删除尾端元素   
  61.     {  
  62.         finish--;  
  63.         finish->~T();  
  64.     }  
  65.       
  66.     void erase(iterator first,iterator last)//清除[first,last)的所有元素   
  67.     {  
  68.         int j = end()-last;  
  69.         for(int i=0;i<j;i++){  
  70.             *(first+i) = *(last+i);  
  71.         }  
  72.         while(end()>first+j){  
  73.             pop_back();  
  74.         }  
  75.     }  
  76.       
  77.     void erase(iterator position)//清除指定位置元素   
  78.     {  
  79.         erase(position,position+1);  
  80.     }  
  81.       
  82.     void clear(){//清空vector   
  83.         erase(begin(),end());  
  84.     }  
  85.       
  86.     void insert(iterator position,int n,const reference x);//从position开始插入n个元素,每个元素的初始值为x   
  87.     //void insert_aux(iterator position, const reference x);//重新分配空间,并完成已有成员的搬移   
  88.       
  89. private:  
  90.     iterator start;  
  91.     iterator finish;  
  92.     iterator end_of_storage;  
  93. };  
  94.   
  95. template <class T>  
  96. void MyVector<T>::insert(iterator position,int n,const reference x)//从position开始插入n个元素,每个元素的初始值为x   
  97. {  
  98.     /* 
  99.     STL的vector<class type>::insert(type * , int , const type &) 作用:在指定位置插入元素,有可能引起扩容 
  100.     当插入导致finish 指针大于 end_ofstorage 时,就需要扩容 
  101.     */  
  102.       
  103.     iterator i = start;//old_start   
  104.     iterator new_finish;//不扩容的话指向old_start,扩容的话指向new_start   
  105.     iterator old_start = start,old_finish = finish;  
  106.     bool needToDestory = false;  
  107.     if(finish+n > end_of_storage){  
  108.   
  109.         needToDestory = true;  
  110.   
  111.         const int old_size = size();  
  112.         const int len = old_size + n;  
  113.   
  114.         start = new T[len];  
  115.         new_finish = start;  
  116.         end_of_storage = start + len;  
  117.     }  
  118.     else {  
  119.         new_finish = start;  
  120.         end_of_storage = finish + n;  
  121.     }  
  122.       
  123.     /*原始数据的搬移*/  
  124.     while(i<position) { *new_finish++ = *i++; }  
  125.     /*插入部分的初始化*/  
  126.     while(n--) { *new_finish++ = x; }  
  127.     /*原始数据的搬移*/  
  128.     while(i<finish) { *new_finish++ = *i++; }  
  129.     finish = new_finish;  
  130.   
  131.     /*这里需要释放原有空间*/  
  132.     if(needToDestory==true){  
  133.         while(old_start != old_finish){  
  134.             old_start->~T();  
  135.             old_start++;  
  136.         }  
  137.     }  
  138. }  
  139. /* 
  140. template <class T> 
  141. void MyVector<T>::insert_aux(iterator position,const reference x){ 
  142.     insert(position,1,x);//重新分配空间,并完成已有成员的搬移 
  143. } 
  144. */  
  145. struct Node{  
  146.     Node(){}  
  147.     Node(int a=0,int b=0):x(a),y(b){}  
  148.     int x,y;  
  149. };  
  150.   
  151. int main(){  
  152.     MyVector<Node> test(3);  
  153.       
  154.     cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;  
  155.       
  156.     for(int i=0;i<3;i++){  
  157.         Node a(i,i*i);  
  158.         test.push_back(a);  
  159.         /* 
  160.         push_back()是从end()端插入,而初始化过的vector的end()是和capacity()相等的,所以会发生扩容, 
  161.         也就是说,我们插入的三个点(0,0),(1,1),(2,4)的位置是在a[3],a[4],a[5]中,而a[0],a[1],a[2]中还是初始化时的值, 
  162.         如果觉得这样浪费的话,想把点插入到最开始的位置的话,有以下几种方法: 
  163.          
  164.           NODE 1:可以再申请容器的时候,不指定大小(默认为0),那么后续插入引起扩容,自然就从第一个位置(a[0])开始了 
  165.           NODE 2:用reserve(N)指定大小,这个函数不会修改finish指针,也就是说,finish指针指向的是begin()端 
  166.           PS:reserve()接口这里我没有实现,留到以后有时间加上吧 
  167.           NODE 3:用insert()在指定位置插入点,但是这样会引起扩容 
  168.           NODE ……欢迎补充 ^_^ 
  169.         */  
  170.     }  
  171.       
  172.     cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;  
  173.       
  174.     MyVector<Node>::iterator pi;  
  175.     for(pi = test.begin();pi != test.end();pi++){  
  176.         cout << pi->x << " " << pi->y << endl;  
  177.     }  
  178.       
  179.     /******测试insert()******/  
  180.     test.insert(test.begin(),7,test[5]);//在begin()端插入7个元素,容量变为 size() + 7   
  181.       
  182.     cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;  
  183.       
  184.     MyVector<Node>::iterator pj;  
  185.     for(pj = test.begin();pj != test.end();pj++){  
  186.         cout << pj->x << " " << pj->y << endl;  
  187.     }  
  188.     return 0;  
  189. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值