(1)提前分配足够的空间以避免不必要的重新分配和复制周期
这个情况在 Scott Meyers 的书中得到了很好的解释,这本书叫 :
对于 vector 和 string,在需要更多空间的时候,会做与 realloc 等效的事情。这种类似 realloc 的操作有4个步骤:
1. 分别一个新的内存块,其容量是容器当前容量的数倍。多数实现中,vector 和 string 容量的提升因子在 1.5 和 2 之间。
2. 从容器原来占用的内存中将元素拷贝到新分配的内存中。
3. 释放原有内存中的对象。
4. 释放原有内存。
有了所有这些操作:分配、回收、拷贝和释放,如果说这些步骤(对于性能)极其昂贵,你一点都不应该感到惊讶。当然,你肯定不希望频繁的进行这样的操作。如果这还没有打动你,那么想想每次进行这些步骤的时候,vector 和 string 中所有的迭代器、指针和引用都会失效。这意味着一个简单的插入操作,对于其它使用了当前 vector 或 string 中的迭代器、指针或引用的数据结构,都有可能引起对它们进行更新。
(2)使用 shrink_to_fit() 释放 vector 占用的内存, – clear() 或 erase() 不会释放内存
请注意,shrink_to_fit() 可能没有被所有编译器供应商完全支持。这种情况下,可以使用“Swap 惯用法”来清空 vector,代码如下:
container( c ).swap( c ); // shrink-to-fit 惯用法,用于清空存储空间container ().swap( c ); // 用于清空所有内容和存储空间的惯用法
如果你对此感兴趣,请查看“”一书的条款# 82,其中有针对 swap 惯用法的细节介绍。
(3)在填充或者拷贝到 vector 的时候,应该使用赋值而不是 insert() 或push_back()
这是因为赋值非常有效率,因为它知道要拷贝的 vector 有多大,然后只需要通过内存管理一次性拷贝 vector 内部的缓存。
所以,想高效填充 vector,首先应尝试使用 assignment,然后再考虑基于迭代器的 insert(),最后考虑 push_back。当然,如果你需要从其它类型的容器拷贝元素到 vector 中,赋值的方式不可行。这种情况下,只好考虑基于迭代器的 insert()。
(4)遍历 std::vector 元素的时候,避免使用 std::vector::at() 函数
遍历 vector 有如下三种方法:
1. 使用迭代器 2. 使用 std::vector::at() 成员函数 3. 使用下标 – [ ] 运算符
用 std::vector::at() 函数访问 vector 元素是最慢的一个
(5)在向 vector 插入元素的时候使用 emplace_back() 而不是 push_back()
仅在以下情况下,Emplacement 函数可能会更快:
1. 要添加的值是在 vector 中构造的,而不是赋值的。
2. 传递的参数类型与 vector 中保存的类型不同。例如,如果一个向量包含 std :: string,但我们传递一个字符串值到该 vector。
即使上述两个条件都不成立,如本例所示,你也不要因为在插入时使用 emplacement 而掉以轻心。
更多关于 emplacement vs. insertion 的详细信息,请查看 Scott Meyer 的““一书中的条目#42。