走马观花式地看了一遍《Effective STL》,书很经典,需要再多看几遍,先把这次阅读时候记下的笔记贴出来。
1. 标准STL序列容器:vector、string、deque和list
标准STL关联容器:set、multiset、map和multimap
Vector,list和deque提供给程序员不同的复杂度,因此应该这么用:vector是一种可以默认使用的序列类型,当很频繁地对序列中部进行插入和删除时应该用list,当大部分插入和删除发生在序列的头或尾时可以选择deque这种数据结构。
2.通过自由地对容器和迭代器类型使用typedef,因此不要这么写:
Class Widget{……};
Vector
Widget bestWidget;
Vector
要这么写:
Typedef vector
Typedef WidgetContainer::iteratorWCIterator;
WidgetContainer cw;
Widget bestWidget;
WCIterator I = find(cw.begin(), cw.end(),bestWidget);
3.用empty来代替检查size()是否为0
4.尽量使用区间成员函数代替它们的单元素兄弟
V1.assign(v2.begin() + v2.size()/2,v2.end());
V1.insert(v1.end(),v2.begin()+v2.size()/2,v2.end());
区间插入:insert(iterator position,//区间插入的位置
InputIteratorbegin,//插入区间的起点
InputIteratorend)//插入区间的终点
关联容器使用它们的比较函数来决定元素要放在哪里,所以它们省略了position参数
Void container::insert(InputIterator begin,InputIterator end);
区间删除:每个标准容器都提供了一个区间形式的erase,但是序列和关联容器的返回类型不同。序列容器提供了这个:
Iterator container::erase(iterator begin,iterator end);
而关联容器提供这个:
Void container::erase(iterator begin,iterator end);
区间赋值:所有标准列容器都提供了区间形式的assign:
Void container::assign(InputIterator begin,InputIterator end);
5.C++里的一条通用规则—几乎任何东西都可能被分析成函数声明。如
Class Widget{};//假设Widget有默认构造函数
Widget w();//这里并没有声明一个叫做w的Widget,它声明了一个叫做w的没有参数且返回Widget的函数。
6.当使用new得指针的容器时,记得在销毁容器前delete那些指针
Void doSomething()
{
Vector
For(vector
{
Delete *I;
}
}
使用智能指针:
Void dosomething()
{
Typedef boost::shared_ptr
Vector
For(int I = 0; i
{
Vwp.push_back(SPW(new Widget));
}
}
7当你拷贝一个auto_ptr时,auto_ptr所指向的对象的所有权会转移给拷贝的auto_ptr所指向的对象,被拷贝的auto_ptr则为NULL;
8.在删除选项中仔细选择
c.erase(remove(c.begin(),c.end(),1963),c.end())//当c时vector,string或deque时,erase-remove惯用法是去除特定值的元素的最佳方法
这方法也适用于list
c.remove(1963);
对于关联容器,解决问题的适当方法是调用erase:
c.erase(1963);//这不仅是正确的,而且很高效,只花费对数时间。序列容器的基于删除的技术需要线性时间。
9.线程安全
10.使用reserve来避免不必要的重新分配
Size()告诉你容器中有多少元素。它没有告诉你容器为它容纳的元素分配了多少内存。
Capacity()告诉你容器在它已经分配的内存中可以容纳多少元素。
Resize()强制把容器改为n个元素。调用resize之后,size将会返回n.如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果N大于当前容量,在元素加入之前会发生重新分配。
Reserve()强制容器把它的容量的改为至少N,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。