Wednesday, November 23, 2005

STL容器的内存增长

在C语言中,如果我们分配了一个能容纳10个元素的数组arr,
如果arr中已经含有了10个元素,我们又想向其中加入一个元素,
这时就需要进行内存重分配了,
向C++标准STL容器添加元素同样会面临类似的内存增长问题。

完成上述所需任务,我们需要做以下几件事:
1.分配有足够空间的一块新内存;
2.把原数组所有元素复制到新内存;
3.销毁原数组的所有元素对象;
4.释放原数组所占内存空间。

由上可见,内存重新分配后元素通常都不再保存在原有的内存地址,
内存重新分配捎带进行的元素复制代价不菲(复制元素,销毁对象、释放内存)。
C++把内存管理的重任从程序员肩上挑了过去,
每当调用insert或者push_back/front等添加元素到STL容器中会自动判断是否进行上述4步。

可以想像出,如果在内存重分配前用一些指针变量保存了数组arr的元素地址,
在进行重分配后,这些指针通常都将指向无效的地址。
向C++的STL的容器中加入新元素时,
此前保存的迭代器变量遇到内存增长后也将是无效的。

避免内存重分配在程序运行效率、正确性方面都有重要意义,
如果在C++程序中确切知道某个容器需要容纳的元素总数,
可以直接用reserve成员预留出足够的空间,
使其后向其增加元素不会引起内存增长。

1 comment:

清风居士 said...

内存增长适用于占连续内存空间的线性容器,如string,vector。
《Effictive STL》第14Item详细介绍了reserve函数,并与其它3个函数相比较:
size()返回容器现有元素个数。
capacity()返回容器当前内存能容纳的元素个数。
resize()强制设置容器的元素个数,可能引起内存增长,抛弃已有元素或者补充默认元素。
reserve()现在内存可能不变或者增加,其中元素保持不变。