0x01 vector构造函数

adfb98be36cf58f17c2a79b8087f429

除了第一种,其他几种基本都是拷贝构造而来的。

1
2
vector<int>v(10,100);
//压入10个100的int数

拷贝构造函数

1
2
vector<int>v2(v);
//拷贝了v的10个100

0x02 vector赋值操作

image-20240219145512229

第一种就是等号运算符重载,直接v1 = v2赋值就好了。

0x03 vector容量和大小

image-20240219153402588

empty( ),若容量为空则返回true,不为空则返回false。

capacity( )是返回容器的容量的函数,容器的容量不小于容器中元素的个数(常识)。

resize函数能调整容器的大小(长度size,并非容量)。

resize函数若不指定填充的元素elem,则默认填充0。

0x04 vector插入和删除

image-20240219160518544

这里重点记录一下迭代器修改元素的方法。

1
2
3
//迭代器插入法
v1.insert(v1.begin(),100);
//在v1.begin()的位置插入100,v1.begin()是指向首元的迭代器

注意const_iterator pos 位置是传入迭代器就好了。

0x05 vector数据存取

image-20240219161554444

没啥好注意的,一般都用[ ]重载来访问

0x06 vector互换容器

image-20240219161831638

实现两个容器内元素进行互换。

巧用swap可以收缩内存空间。

实际情况:假设你定义了一个容量很大的容器时,若当你不需要使用这么大的容量时,通过resize函数只能改变容器的大小,而容量不会改变,这时候多余的容量就遭到了浪费。

比如你push_back了10000个数据,容量会给你自动扩展到约13000的数据,这时候你resize(3),将容器的大小调整至3,这时候容量依然是13000左右。这会造成浪费!!!

解决方法,匿名函数和swap函数

1
vector<int>(v).swap(v);

vector(v) 默认构造匿名对象。这里会根据v目前所用的元素个数的大小来初始化匿名对象,在这里的例子里,大小为3。

然后调用 .swap(v),v的容量经过swap交换后是 3,大小(size)也是 3,不会造成空间浪费了,匿名对象的容量经过swap后占用很大,但是在这一行执行完后匿名对象会被销毁,就不会造成空间浪费了。

image-20240219182013042

0x07 vector预留空间

image-20240219182129095

预留空间是为了,减少vector在动态扩展容量时的扩展次数。

vector容器在创建的时候是会先预留较多的空间来应对之后的扩展,比如我push_back了10个数据,编译器会事先将这个vector容器的容量设定成100多(大概的,反正比容器大小,元素个数多)。当你继续扩展这个容器时,可能超过了事先预留好的容量,这时候编译器会将原先的容器内的数据拷贝到一个新的,容量更大的容器中,虽然容器的名字不会变,但是该容器的首地址会发生了改变(因为数据被拷贝存储到了一个新开辟的空间)。

经过浅显的测试,10000个数据在push_back时大约会发生30次的新开辟存储空间的情况,浪费了时间资源。

测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
vector<int> v;
//统计开辟次数
int cnt = 0;
int *p = NULL;
for(int i = 0; i < 10000; i++){
v.push_back(i);
//当每次开辟新空间时,v[0]的地址就会变化,以此为参照统计开辟次数
if(p!= &v[0]){
p = &v[0];
cnt++;
}
}
cout << cnt;

所以一开始就先预留出容量,能减少扩展次数。