vector源码2(参考STL源码--侯捷):空间分配、push_back
vector源码2(参考STL源码--侯捷)
vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效
vector源码3(参考STL源码--侯捷):pop_back、erase、clear、insert
vector的构造和内存管理
vector所采用的数据结构非常简单:线性连续空间,它是由两个迭代器start和finish分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端:
class vector //详细源码可见
{
..........
protected:
typedef simple_alloc<value_type,Alloc> data_allocator; //simple_alloc是SGI STL的空间配置器
iterator start; //表示目前使用空间的头
iterator finish; //表示目前使用空间的尾
iterator end_of_storage; //表示目前可用空间的尾
..........
为了降低空间速配成本,vector的实际配置大小是原来容器大小的2倍,见下图:
#include<bits/stdc++.h>
using namespace std; int main(){
vector<int> v(,);
cout<<v.size()<<" "<<v.capacity()<<endl; //3 3
v.push_back();
cout<<v.size()<<" "<<v.capacity()<<endl; //4 6
v.push_back();v.push_back();v.push_back();
cout<<v.size()<<" "<<v.capacity()<<endl; //7 12 for(int i=;i<v.size();i++){ //3 3 3 5 6 7 8
cout<<v[i]<<' ';
}
cout<<endl; v.pop_back();v.pop_back();
cout<<v.size()<<" "<<v.capacity()<<endl; //5 12
v.pop_back();
cout<<v.size()<<" "<<v.capacity()<<endl; //4 12 vector<int>::iterator it=find(v.begin(),v.end(),);
if(it!=v.end())
v.erase(it);
cout<<v.size()<<" "<<v.capacity()<<endl; //3 12 it=find(v.begin(),v.end(),);
if(it!=v.end())
v.insert(it,,);
cout<<v.size()<<" "<<v.capacity()<<endl; //7 12 for(int i=;i<v.size();i++){ //7 7 7 7 3 3 3
cout<<v[i]<<' ';
}
cout<<endl; v.clear();
cout<<v.size()<<" "<<v.capacity()<<endl; //0 12
return ;
}vector缺省使用alloc作为空间配置器,并据此另外定义了一个data_allocator,为的是更方便以元素大小为配置单位,data_allocator::deallocate(n)表示配置n个元素空间,vector提供许多constructors一个允许我们指定空间大小及初值。
/构造函数,允许指定vector大小n和初值value
vector(size_type n,const T& value){fill_initialize(n,value);}
//填充并初始化
void fill_initialize(size_type n,const T& value){ //用于vector初始赋值
start=allocate_and_fill(n,value);
finish=start+n;
end_of_storage=finish;
}
//配置空间,并填满内存
iterator allocate_and_fill(size_type n,const T& x){
iterator result=data_allocator::allocate(n)
/*全局函数,uninitialized_fill_n()有3个参数:
迭代器first指向欲初始化空间的地址的起始处
*初始化空间的大小n
*初始化的值x*/
uninitialized_fill_n(result,n,x);
return result;
}
uninitialled_fill_n()会更根据第一参数类型来决定是使用算法fill_n()或反复调用construct();fill_n()多用于初始化多个相同数据,construct()多用于插入一个数据。
当我们利用push_back()插入元素是,vector会先检查备用空间是否充足,如果充足,尾部插入数据,否则,先扩充空间,再插入数据,这里就要考虑到重新分配、移动数据、释放空间的问题。
void push_back(const T& x){//添加元素
if(finish !=end_of_storage)//是否超出最大可容纳空间{
/*全局函数,construct()接收一个指针p和一个初值value,该函数的用途就是将
初值value设定到指针锁指的空间上。
*/
construct(finish,x);
++finish;
}
else {
insert_aux(end(),x); //vector的成员函数
}
}
insert_aux ()的具体实现如下:
template <class T,class Alloc>
void vector<T,Alloc>::insert_aux(iterator position, const T &x){
if(finish!=end_of_storage){//还有备用空间
//在备用空间起始处构造一个元素,并在vector最后一个元素值为其初值
construct(finish,*(finish-));
++finish;
T x_copy=x;
copy_backward(position,finish-,finish-);//将position到finish-2位置的元素后移到finish-1位置
*position=x_copy;
}
else{//已无备用空间
const size_type old_size=size();
const size_type len=old_size !=? *old_size:;
//以上配置原则:如果为0,则配置1,否则配置原来大小的2倍
iterator new_start=data_allocator::allocate(len);//实际配置
iterator new_finish=new_start;
try{
//将原vector元素拷贝过来
new_finish=uninitialized_copy(start,position,new_start);//迭代器start指向欲初始化空间的起始位置、迭代器position指向输入端的位置结束(前闭后开)、迭代器new_start指向输出端的起始位置
//为新元素设置初值
construct(new_finish,x);
++finish;
//将原vector的备用空间中的内容也从新拷贝过来
new_finish=uninitialized_copy(position,finish,new_finish);
}
catch(...){
destory(new_start,new_finish);
data_allocator::deallocate(new_start,len);
throw;
}
//析构释放原vector
destory(begin(),end());
deallocate();
//调整迭代器,指向新的vector
start=new_start;
finish=new_finish;
end_of_storage=new_start+len;
}
}可以看到,动态增加是直接开辟新的2倍的空间,进行数据的复制,而不是直接在原来vector后面开辟空间,因为无法保证其后面是否有足够空间,这也就说明指向原vector的所有迭代器就都失效了(查看示例)。
vector源码2(参考STL源码--侯捷):空间分配、push_back的更多相关文章
- vector源码3(参考STL源码--侯捷):pop_back、erase、clear、insert
vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷):空间分配.push_back vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 v ...
- vector源码1(参考STL源码--侯捷):源码
vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...
- list源码1(参考STL源码--侯捷):list节点、迭代器、数据结构
list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...
- list源码2(参考STL源码--侯捷):constructor、push_back、insert
list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...
- list源码4(参考STL源码--侯捷):transfer、splice、merge、reverse、sort
list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...
- list源码3(参考STL源码--侯捷):push_front、push_back、erase、pop_front、pop_back、clear、remove、unique
list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...
- vector源码(参考STL源码--侯捷):空间分配导致迭代器失效
vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...
- STL 源码分析 (SGI版本, 侯捷著)
前言 源码之前,了无秘密 algorithm的重要性 效率的重要性 采用Cygnus C++ 2.91 for windows cygwin-b20.1-full2.exe 下载地址:http://d ...
- STL源码剖析之序列式容器
最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...
随机推荐
- shell字符串分割截取和转换总结
一:字符串的截取 假定有定义变量VAR=mm/aa/bb/dd 1.获取字符串长度:echo "${#VAR}",即输出11: 2.非贪婪模式删除左边的,保留右边的:echo &q ...
- HTTP 错误 404.17 - Not Found和 HTTP 错误 404.2 - Not Found 解决办法
HTTP 404.2 - Not Found" IIS 7.5 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理 解决办法: 使用aspnet_regiis.exe注册.NET Fr ...
- 20155205 2016-2017-2 《Java程序设计》第2周学习总结
20155205 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 变量 变量在命名时有一些规则,它不可以使用数字作为开头,也不可以使用特殊字符. 对常用忽略符 ...
- C++的重载流输出运算符
// 下列代码输出什么?#include <iostream>#include <string>// typedef basic_ostream<char> ost ...
- 实战--利用SVM对基因表达标本是否癌变的预测
利用支持向量机对基因表达标本是否癌变的预测 As we mentioned earlier, gene expression analysis has a wide variety of applic ...
- AFNetworking网络请求数据
//创建AFNetworking的请求操作 AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWit ...
- Lib作为“静态库”与“动态库”中的区别
Lib作为“静态库”与“动态库”中的区别 0. 前言: 什么是静态连接库: 静态库在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中.因此对应的链接方式称为静态链接. 为什么 ...
- shell工具-cut
cut cut的工作就是“剪”,具体说就是在文件中负责剪切数据用的.cut命令从文件的每一行剪切字节.字符.和字段并将这些字节.字符和字段输出 基本用法 cut [参数] filename # 说明: ...
- LCA tarjan+并查集POJ1470
LCA tarjan+并查集POJ1470 https://www.cnblogs.com/JVxie/p/4854719.html 不错的一篇博客啊,让我觉得LCA这么高大上的算法不是很难啊,嘻嘻嘻 ...
- js-倒计时原理
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> ...
