C++ vector插入操作insert解释
首先vector的底层实现也是普通数组。
vector的大小有两个维度一个是size一个是capicity,size就是我们平时用来遍历vector时候用的,例如:
for (int i = 0; i < vec.size(); i++) {
}
而capicity是vector底层数组(就是普通数组)的大小,capicity可不一定就是size。
当insert数据的时候,如果已经大于capicity,capicity会成倍扩容,但对外暴漏的size其实仅仅是+1。
那么既然vector底层实现是普通数组,怎么扩容的?
就是重新申请一个二倍于原数组大小的数组,然后把数据都拷贝过去,并释放原数组内存。
举一个例子,如图:
原vector中的size和capicity相同都是3,初始化为1 2 3,此时要push_back一个元素4。
那么底层其实就要申请一个大小为6的普通数组,并且把原元素拷贝过去,释放原数组内存,注意图中底层数组的内存起始地址已经变了。
同时也注意此时capicity和size的变化,关键的地方我都标红了。
以上内容来自代码随想录贪心算法:根据身高重建队列(续集)
下面对插入元素后内存地址可能改变的说法进行验证,还是使用leetcode 406题的题解来验证,修改后代码如下:
class Solution {
public:
static bool cmp(vector<int>& people1, vector<int>& people2) {
if (people1[0] == people2[0]) return people1[1] < people2[1];
return people1[0] > people2[0];
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), cmp);
vector<vector<int>> res = {{0,0}}; //这里赋值初始化是为了便于下面访问首个元素,获取地址
for (int i = 0;i < people.size();i++) {
int h = people[i][1];
cout<<"插入前首元素地址:"<<&(*res.begin())<<endl; // 这里获取插入元素前的首元素的地址;获取vector迭代器的地址方法:&(*it)
res.insert(res.begin() + h, people[i]);
cout<<"插入后首元素地址:"<<&(*res.begin())<<endl; // 这里获取插入元素后的首元素的地址
}
return vector<vector<int>>(res.begin(), res.end()-1);
}
};
//输入如下:
/*
插入前首元素地址:0x6030000000a0
插入后首元素地址:0x6040000000d0
插入前首元素地址:0x6040000000d0
插入后首元素地址:0x6080000000a0
插入前首元素地址:0x6080000000a0
插入后首元素地址:0x6080000000a0
插入前首元素地址:0x6080000000a0
插入后首元素地址:0x610000000140
插入前首元素地址:0x610000000140
插入后首元素地址:0x610000000140
插入前首元素地址:0x610000000140
插入后首元素地址:0x610000000140
*/
可以看出有几次地址在插入后发生了变化,下面对这几次变化做一个说明:
从下图中可以模拟出res数组内存不断变化的过程,当插入元素超出capicity时,数组就会新开辟一块空间为原来2倍的内存,其首地址不同于原来的数组地址,然后再插入元素;而插入元素不超出capicity时,不扩容,内存空间也不变化。