一、通用容器大小操作
所有容器类型都提供4种与容器大小相关的操作,包括:
(1)c.size():返回容器c中的元素个数
(2)c.max_size():返回容器c可容纳的最多元素个数,返回类型为c::size_type
(3)c.empty():返回标记容器大小是否为0的布尔值
(4)c.resize(n):调整容器c的长度大小,使其能容纳n个元素,如果n
(5)c.resize(n, t):调整容器c的大小,使其容纳n个元素,所有新添加的元素值都为t
容器类型提供resize操作来改变容器所包含的元素个数。如果当前的容器长度大于新的长度值,则该容器后部的元素会被删除;如果当前的容器长度小于新的长度值,则系统会在该容器后部添加新元素:
vector ivector(10, 42); //10 ints: each has value 42
ivector.resize(15); //adds 5 elements of value 0 to back of ivector
ivector.resize(25, -1); //adds 10 elements of value -1 to back of ivector
ivector.resize(5); //erases 20 elements from the back of ivector
resize操作可带有一个可选的元素值形参。如果在调用该函数时提供了这个参数,则所有新添加的元素都初始化为这个值。如果没有这个参数,则新添加的元素采用值初始化。
需要注意的是:resize操作可能会使迭代器失效,对于所有的容器类型,如果resize操作压缩了容器,则指向已删除的元素的迭代器失效。
二、vector容器的自增长
为了支持快速的随机访问,vector容器的元素以连续的方式存放——每一个元素都紧挨着前一个元素存储。
已知元素是连续存储的,当我们在容器内添加一个元素时,如果容器中已经没有空间容纳新的元素,此时,由于元素必须连续存储以便索引访问,所以不能在内存中随便找个地方存储这个新元素,于是,vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素,存放在旧存储空间中的元素被复制到新存储空间里,接着插入新元素,最后撤销旧的存储空间。
需要注意的是:如果vector容器在每次添加新元素时,都要这么分配和撤销内存空间,其性能将会非常慢,简直无法接受。
vector的优势在于:以最小的代价连续存储元素,由此而带来的访问元素的便利弥补了其存储代价。
为了使vector容器实现快速的内存分配,其是实际分配的容量要比当前所需的空间多一些。vector容器预留了这些额外的存储区,用于存放新添加的元素。于是,不必为每个新元素重新分配容器。所分配的额外内存容量的确切数目因库的实现不同而不同。比起每添加一个新元素就必须重新分配一次容器,这个分配策略带来显著的效率。事实上,其性能非常好,因此在实际应用中,比起list和deque容器,vector的增长效率通常会更高。
vector提供了两个成员函数:capacity和reserve,使程序员可与vector容器内存分配的实现部分交互工作。capacity操作获取容器能够存储的元素总数,而reserve操作则告诉vector容器应该预留多少个元素的存储空间。
弄清楚容器的capacity(容量)和size(长度)的区别非常重要,size指容器当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。默认情况下,创建完vector后,其size和capacity都为0,但是向vector插入元素后,会发生变化,通常capacity会比size大,比如:
vector ivec;
for (vector::size_type ix=0; ix!=24; ++ix)
{
ivec.push_back(ix);
}
cout << "ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
上面代码输出结果如下:
ivec: size: 24 capacity: 32
当然,你也可以用reserve来为vector预留额外的存储空间:
ivec.capacity(50);
cout << "ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
该操作只改变了容器的capacity,而不改变size大小,则其输出如下:
ivec: size: 24 capacity: 50
如果将预留的容量用完,又当如何:
while (ivec.szie() != ivec.capacity())
{
ivec.push_back(0);
}
cout << "ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
只要有剩余容量,vector就不会做任何内存分配或重新分配的工作,直至耗尽了所有预留的容量,则其输出如下:
ivec: size: 50 capacity: 50
如果此时再添加新元素,则vector必须为自己重新分配内存空间:
ivec.push_back(51);
cout << "ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
当vector不得不分配新的存储空间时,会以加倍当前容量的分配策略(具体策略与库的实现相关)实现重新分配,则其输出结果如下:
ivec: size: 51 capacity: 100
此外,每种实现都要遵循以下原则:确保push_back操作高效地在vector中添加元素。从技术上来说,在原来为空的vector容器上n次调用push_back函数,从而创建拥有n个元素的vector容器,其执行时间永远不能超过n的常量陪。
阅读(1801) | 评论(0) | 转发(0) |