条款1:仔细选择你的容器
标准STL序列容器:vector,string,deque和list
标准STL关联容器:set,multiset,map和multimap
非标准序列容器:slist(单向链表)和rope(重型字符串——不懂)
非标准关联容器:hash_set,hash_multiset,hush_map和hash_multimap
vector<char> == string
vector可作为标准关联容器的替代品
几种标准非STL容器:数组,bitset,valarray,stack,queue和priority_queue
情况:
任意位置插入:序列容器
关心元素在容器中的顺序:避免使用散列容器
必须使用标准C++容器:除去散列容器、slist、rope
需要随机访问迭代器-->限于vectro、deque、string,也可能rope
需要双向迭代器-->除去slist和散列容器
插入或删除数据,非常在意容器内有元素移动,放弃连续内存容器
数据内存布局需要兼容C:只能用vector
查找速度:散列容器,排序vector,标准的关联容器——大概是这个顺序
介意容器底层使用引用计数:避开string,rope,可以考虑vector<char>
条款2:小心对“容器无关代码”的幻想
数组泛化为容器,参数化了所包含的对象的类型,函数泛化为算法,参数化了所有的迭代器的类型。指针泛化为迭代器,参数泛化了所有指向的对象的类型。
标准的内存相邻容器提供随机访问迭代器。
标准基于节点的容器都提供双向迭代器。
序列容器支持push_front或push_back,关联容器不支持。
关联容器提供对数时间复杂度的lower_bound,,,
多使用typedef
条款3:使容器里对象的拷贝操作轻量而正确
容器容纳的对象并不是程序员添加的对象,只是指定对象的拷贝,同样取出也是拷贝。
容器内拷贝很常见,在数据移动和排序中。
由于继承的存在,若容器指定类型为基类,派生类对象放入后将出现特殊部分缺失
条款4:用empty来代替检查size()是否为0
if(c.size() == 0) —— if(c.empty())
理由:更简单,对于list实现,size花费线性时间
list在splice操作后,如果用size无法提供一个常数的时间给用户使用,empty可以提供,毕竟lishi是一个标准容器,需要广泛高效使用,
条款5:尽量使用区间成员函数代替它们的单元素兄弟
vector中函数assign(),功能:分配数据
区间成员函数操作比显式循环赋值操作效率更高,而且代码更简洁。
尽量避免使用COPY,因为:几乎所有目标区间被插入迭代器指定的copy的使用都可以用调用的区间成员函数的来代替。
显式循环赋值或拷贝需要重复的进行赋值和拷贝操作,大大增加了执行时间。而且需要不断的插入内存,vector需要分配更多新内存来满足单元素的重复赋值和拷贝操作。string和deque的道理和vector类似。但是deque的内存方式和vector和string不同,内存方式不适用于deque。对于list,过多重复对list中的一些节点的next和prev指针赋值。
区间成员函数:
区间构造:
container::container(InputIterator begin, // 区间的起点
InputIterator end); // 区间的终点
区间插入:
void container::insert(iterator position, // 区间插入的位置
InputIterator begin, // 插入区间的起点
InputIterator end); // 插入区间的终点
关联容器
void container::insert(lnputIterator begin, InputIterator end);
区间删除:
序列容器:
iterator container::erase(iterator begin, iterator end);
关联容器:
void container::erase(iterator begin, iterator end);
区间赋值:
void container::assign(InputIterator begin, InputIterator end);