vector容器的自增长
vector容器的元素以连续的方式存放,即每一个元素都紧挨着前一个元素存储。分配内存时实际分配的容量比当前需要的空间多一些,预留的存储区用于存放新添加的元素,不必为每个新元素重新分配容器。
list容器增加新元素时标准库只需创建一个新元素,然后将新元素连接在已存在的链表中,不需要重新分配存储空间,也不必复制任何已存在的元素。
标准库的实现者使用这样的内存分配策略:以最小的代价连续存储元素,由此带来的访问元素的便利弥补了其存储代价,因此在实际应用中,比list 和 deque 容器,vector的增长效率通常会更高。
size(长度):指容器当前拥有的元素个数;
capacity(容量): 则指容器在必须分配新存储空间之前可以存储的元素总数。
vector<int> ivec;
cout << "ivec:size:" << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
for(vector<int>::size_type ix = 0; ix != 24; ++ix)
ivec.push_back(ix);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
ivec.reserve(50);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
while(ivec.size() != ivec.capacity())
ivec.push_back(0);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
ivec.push_back(42);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
while(ivec.size() != ivec.capacity())
ivec.push_back(1);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
ivec.push_back(11);
cout << "ive:size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
容器的选用
vector 和 deque 容器提供了对元素的快速随机访问,付出的代价是在容器的任意位置插入或删除元素比在容器尾部插入和删除的开销更大。
vector 除了容器尾部外,任何其位置上的insert或erase都要移动被insert和erase元素右边所有的元素。
list 容器表示不连续的存储区域,允许向前和向后逐个遍历元素,在任何位置都能快速insert和 erase(删除),不需要移动其它元素,付出的代价是元素的随机访问开销较大(访问某个元素要求遍历所涉及的其他元素)。
deque容器从队列的两端insert和erase元素都非常快,在中间insert和erase付出更高的代价,dque提供了list 和 vector的一些性质:
- 与vector一样,在中间inser和erase 元素效率比较低。
- 不同于 vector ,在首部操作就像尾部一样。
- 与vector一样不同于list ,deque支持对所有元素的随机访问。
- 在deque首部或尾部inser不会使作何迭代器失效,在首部或尾部删除时,只会使指向被删除元素的失效。在任何其它位置的确insert和erase操作将使指向该容器元素的所有迭代器都失效。
选择容器的提示
(1)要求随机访问元素,使用vector或deque。
(2)在容器中间insert或erase,使用list。
(3)不是在中间,而是在首部或尾操作,使用deque。
(4)如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,可在输入时将元素读入list,接着对此容器重新排序,使其适合顺序访问,然后将排序后的list 复制到一个vector容器。
(5)如果既需要随机访问又必须在容器的中间位置insert和erase,应用点点优势的操作将决定选择什么类型的容器。
如果无法确定某种应用该采用哪种容器,则编写代码时尝试只使用vector和list容器都提供的操作:使用迭代器,而不是下标,并且避免随机访问元素。在必要时,可很方便地将程序从使用vector修改为使用list。