迭代器失效
不要在容器的元素增/减操作之后使用之前获取的元素引用,指针和迭代器
在遍历一个vector容器,删除其中的负元素并复制所有的非负元素
正确写法
void test1()
{
vector<int> vi{
1,-9,3,-2,0,7,-5};
//expect {1,1,3,3,0,0,7,7};
auto it=vi.begin();
while(it!=vi.end())
{
if(*it<0)
{
it=vi.erase(it);//erase 删除了之前it位置的节点,放回的是删除之后刚才哪个位置的节点,现在往后变了
//这个迭代器不会失效
}
else
{
it=vi.insert(it,*it);//在it这个迭代器位置,插入之前it指向的值
//it指向的是3的位置
//假设之前的是{1,3,-2,0,-7,5}
//插入之后{1,3,3,-2,0,-7,5}
//insert返回的是插入位置的,所以就是第1个3,所以需要向后移动两个位置
it+=2;//
}
}
}
错误写法
void test2()
{
vector<int> vi{
1,-9,3,-2,0,7,-5};
auto it=vi.begin();
auto end=vi.end();
while(it!=end)
{
if(*it<0)
{
vi.erase(it);
++it;
}
}
}
错误点
- end提前保存的,在erase之后,这个end就失效了
- erase删除了it位置的节点,但是又++it,此时这个it已经失效了,这个就是错的
正确修改
it=vi.erase(it);
空间配置器
空间适配器:是一个负责空间的配置与管理,从实现上看,空间配置器是一个动态空间的配置,空间管理,空间的释放
- STL的空间配置器是用于封装STL容器在内存管理的底层细节
C++中,空间配置和释放如下
- new,先调用operator new进行开辟内存空间,再调用构造函数
- delete,先调用对应的稀构函数,再释放内存
而STL的空间配置器把这两部分分开了,
- 内存开辟使用allocate,内存释放使用deallocate
- 对象构造使用construct,对象稀构使用destroy
为了提高内存的管理效率,STL使用了两级的空间配置器,第一级是直接使用malloc,realloc,free,
第二级是使用内存池的技术,来进行管理内存