STL_vector学习笔记
1. vector的底层原理
vector底层使用的是一个自动管理的动态数组,线性连续空间;vecotr的实现技术,关键在于其对大小的控制以及重新配置时数据移动效率。vector是动态空间,会随着新元素的加入,其内部机制会自行扩充空间以容纳新元素。
2. vector源码
vector的底层数据结构是:线性连续空间
iterator start; // 记录目前使用空间的头
iterator finish; // 记录目前使用空间的尾
iterator end_of_storage;// 记录目前可用空间的尾
3. vector的基本操作
3.1. 内存管理例子
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// vector内存管理学习
int i;
vector<int> iv(3,9);
cout << "size = " << iv.size() << endl; // size = 3
cout << "capacity = " << iv.capacity() << endl; // capacity = 3
iv.push_back(1);
cout << "size = " << iv.size() << endl; // size = 4 添加元素时,capacity<size,所以需要扩容
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
iv.push_back(2);
cout << "size = " << iv.size() << endl; // size = 5 添加元素时,capacity > size,所以不需要扩容
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
iv.pop_back();
cout << "size = " << iv.size() << endl; // size = 4
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
iv.push_back(3);
cout << "size = " << iv.size() << endl; // size = 5 添加元素时,capacity > size,所以不需要扩容
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
for(int i = 0;i < iv.size();i++) // 9 9 9 1 3
{
cout << iv[i] << " " ;
}
cout << endl;
vector<int>::iterator ivite = find(iv.begin(),iv.end(),1);
iv.erase(ivite); // 擦去元素2
cout << "size = " << iv.size() << endl; // size = 4
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
for(int i = 0;i < iv.size();i++) // 9 9 9 3
{
cout << iv[i] << " " ;
}
cout << endl;
iv.clear(); // clear()操作,内存并未释放,只是size=0
cout << "size = " << iv.size() << endl; // size = 0
cout << "capacity = " << iv.capacity() << endl; // capacity = 6
vector<int> aaa;
cout<< "新vector 初始内存 = " << aaa.size() << endl;
cout<< "新vector 初始内存 = " << aaa.capacity() << endl;
return 0;
}
3.2. 输出结果
[root@tianyiyi vector]# g++ -std=c++11 vector.cpp -o vector
[root@tianyiyi vector]# ./vector
size = 3
capacity = 3
size = 4
capacity = 6
size = 5
capacity = 6
size = 4
capacity = 6
size = 5
capacity = 6
9 9 9 1 3
size = 4
capacity = 6
9 9 9 3
size = 0
capacity = 6
4. vector扩容问题
vector
扩容(即动态增加大小)并非在源空间之后接续新空间(因为无法保证原有空间之后上游可供配置的空间),而是以原大小的两倍另外配置一块比较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构建新元素,并释放源空间。因此,对vector
的任何操作,一旦引起空间重新配置,那么指向源vector
的所有迭代器就都失效了。
5. 收集vector相关问题
5.1. 问:Vector底层数据结构
vector
底层的数据结构是线性连续空间,其默认构造的方式是0, 之后插入按照1 2 4 8 16 二倍扩容(是按照当前capacity的倍数进行扩容)。注(GCC是二倍扩容,VS13是1.5倍扩容。)
5.2. 问:vector扩容原理概述
新增元素:Vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素;
对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 ;
5.3. 问:主流STL实现的vector初始大小是多少
0
5.4. 问:remove和erase区别
vector
中的remove
是将要删除的元素放置在vector
的尾部,但并不减少vector
的size
vector
中erase
的作用是删除掉某个位置position
或一段区域,减少其size
5.5. 问:erase注意事项
erase
可以删除vector
容器中的一个或者一段元素,在进行单个元素删除后,传入的迭代器指向不变,仍然指向被删除元素的位置,而被删除元素之后的所有元素都镶嵌移动一位,也就是该迭代器实际上是指向了原来被删除元素的下一个元素。正因如此,如果删除了最后一个元素,那么该迭代器就不会指向vector数组了,而是变为野指针
// 错误写法!!!
vector<int>::iterator itr = v.begin()
while(itr != v.end())
{
if(*v == 1)
{
v.erase(itr);
}
itr++; // 如果有删除,那么这个迭代器更新会出错
}
// 正确写法
vector<int>::iterator itr = v.begin()
while(itr != v.end())
{
if(*v == 1)
{
v.erase(itr);
}
else
{
itr++;
}
}
5.6. 问:push_back和emplace_back的区别
区别在于其底层实现机制不一样,
push_back
向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中;而emplace_back
在是实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。