C++ 标准程序库 学习笔记 2012-09-26
1. predicates STL 规定:面对相同的值,predicates 必须返回相同的结果
2. 仿函数, 任何东西,只要行为与函数相似,都可以称为仿函数。(函数行为:可以使用小括号传递参数,籍以调用某个东西)因此,如果定义了一个对象,行为像函数,就可以当作函数来使用,例如:
1 class PrintInt { 2 public: 3 void operator() (int elem) const { 4 std::cout << elem << " "; 5 } 6 }; 7 8 int main () 9 { 10 vector<int> coll; 11 12 //insert elements form 1 to 9 13 for (int i = 1; i <= 9; ++i) { 14 coll.push_back(i); 15 } 16 17 //print all elements 18 for_each (coll.begin(), coll.end(), 19 PrintInt()); //operation 20 cout << endl; 21 }
3. 仿函数的优点:
a. 仿函数是“smart functions" (智能型函数)
仿函数不同于普通函数,它可以拥有成员函数和成员变量,这也就意味着,它可以拥有状态(state)。事实上,在同一个时间里,由仿函数代表的单一函数里,可能有不同的状态。同时,我们还可以在执行期(runtime)对它们进行初始化。
b. 每个仿函数都有自己的型别
一般函数只有标记式不同的时候,才算型别不同。而仿函数即使标记式相同,也可以拥有不同的型别。由于每一个仿函数均有一个自己的型别, 因此我们可以将函数行为当作 template 参数来运用。这使得不同型别的容器可以使用相同类别的仿函数做为排序准则。确保不会在排序准则不同的群集(collection)之间赋值、合并或比较。我们甚至可以设计仿函数继承体系,以此完成某些特别的事情。
c. 仿函数通常比一般函数速度快
就 template 概念而言,由于更多细节在编译期间就已经确定,所以通常可能进行更好的最佳化,所以,传入一个仿函数,可能获得更好的性能。
4. vector 模拟出了一个动态数组,本身是一个“将元素置于动态数组中加以管理”的一个抽象概念。它本身支持随机存取,但是增删元素时,在末端性能较好。
5. 对于 vector 而言,它配置了比实际容量更多的内存,它的容量很重要:一旦需要重新配置内存,和 vector 相关的所有 references、pointers、iterators都会失效。重新配置内存很耗时间。
6. 对于 vector 容器,可以通过 reserve 进行重新分配内存,来增加容量,但是不能通过它减少容量, std::vector<T>(v).swap(v) 可以完成减少容量的工作。
7. 对于 vector 中,c.at (idx)、c[idx]、c.front()、c.back()中,只有 c.at (idx) 进行了范围检查,当越界时会抛出 out_of_range 异常,其它操作均未进行检查。因此,再使用的时候,需要确保索引有效。
8. vector 保证了 vector 所有元素分布于连续的空间中,因此 保证了对于vector内的任意合法索引,以下表达式一定为true:
&v[i] = &v[0] + i;
因此,不管出于什么原因,只要需要一个元素类型为 T 的数组,就可以采用 vector<T>,然后传递第一个元素的地址给它,如下所示:
1 std::vector<char> v; 2 3 v.resize(41); 4 strcpy(&v[0], "hello, world"); 5 printf("%s\n", &v[0]);
9. vector 中的 vector<bool> 属特化版本。
10. deques 是一个与 vector 相似的,头尾两端都开放,可以进行快速安插和删除操作的容器。
11. 与 vector 相比, deques 功能上的不同之处在于:
a. 两端都能进行快速安插和移除元素(vector 只能在尾部进行)。并且可以在分期摊还的常数时间内完成。
b. 存取元素时,deque 内部会多一个间接过程,所以元素的存取和迭代器的动作会稍微慢一些。
c. 迭代器需要在不同的区块间跳转,所以必须是特殊的智能指针,非一般指针。
d. 在对内存区块有限制的系统中(如PC系统),deque 可以内含更多元素,因为它使用不止一块内存。因此 deque 的 max_size() 会更大。
e. deque 不支持对容量和内存重分配时机的控制。特别的是,除了头尾两端,在任何地方进行插入和删除元素操作,都会使得所有指向 deque 元素的 pointers、references、iterators失效。不过,deque 的内存重分配优于 vector ,因为内部结构显示,deque 不必在内存重分配时复制所有元素。
f. deque 的内存块不被使用时,会被释放。deque 的内存大小是可以缩减的。不过,具体做法,由不同的版本定义。
12. 如下情形,最好采用 deque :
a. 需要在两端进行安插和移除元素。
b. 无需引用容器内的元素。
c. 要求容器释放不再使用的元素。
13. deque 不提供容量操作(capacity() 和 reserve() )。
14. deque 的元素的插入和移除都可能导致内存的重新分配,所以任何插入或删除的动作都会使所有指向 deques 元素的 pointers、references 和 iterators 失效。唯一例外的是在头部或尾部插入元素,动作之后,pointers 和 references 仍然有效(但 iterators 就没这么幸运了)。