C++标准程序库(学习笔记)三

来源:互联网 发布:内存频率测试软件 编辑:程序博客网 时间:2024/05/18 02:04
P174
当你对着容器赋值元素时,源容器的所有元素被拷贝到目标容器中,后者原本所有的元素全部被移除,所以容器的赋值代价比较高昂
vector的容量之所以很重要,有以下两个原因:
     1.一旦内存重新配置,和vector元素相关的所有references\pointers\iterators都会失效
     2.内存重新配置很耗时间
vector的容量不会缩减,所以,即使删除元素,其reference、pointers、iterators也会继续有效,继续指向动作发生前的位置,然而安插操作却可能使其失效,因为安插导致重新分配内存

P184
任何地点只要你需要一个动态数组,你就可以使用vector,
注意,千万不要把迭代器当做第一元素的地址来传递。vector迭代器是由实作版本定义的,也许并不是一个一般指针

P193
list不支持随机存取,所以在list上随机遍历元素时很慢的,但它在任何位置上的安插和移除都非常快,且安插和移除操作不会使iterator、pointer、reference、失效。list的迭代器是双向(非随机)迭代器
linked list的一大好处就是不论在任何位置,元素的安插和移除都只需要常数时间
splice移动元素c1.splise(pos,c2);c1.splise(pos,c2,c2pos);c1.splise(pos,c2,c2beg,c2end);
sort
merge

p204
自动排序造成sets和multisets一个重要的限制:你不能直接改变元素值,因为这样会打乱原本正确的顺序,因此,要改变元素值,必须先删除旧元素,再插入新元素,这里提供的接口正反应了这种行为:
sets和multisets不提供用来直接存取元素的任何操作函数。
通过迭代器存取有一个限制:从迭代器角度看,元素值是常数。
以上限制对map同样适用
查询操作:count(),find(),lower_bound(),upper_bound(),equal_range()


P232
移除“迭代器所指元素问题”:
如果直接移除:
     for(pos=coll.begin();pos!=coll.end();++pos)
          if(pos->second==value)
               coll.erase(pos);
则会造成程序在运行期崩溃,因为coll.erase(pos)后,pos不在成为一个有效的coll迭代器,对其++操作几乎必定会造成崩溃
所以要移除元素应该这样:
     for(pos=coll.begin();pos!=coll.end();)
          if(pos->second==value)
               coll.erase(pos++);
          else
               ++pos


p255
关联式容器拥有自动排序的能力,并不意味着它们在排序方面的执行效率更高,事实上由于关联式容器每安插一个新元素,都要进行一次排序,所以速度反而不及序列式容器经常采用的手法:先安插所有的元素,然后调用排序算法进行一次排序。

P286
迭代器相关辅助函数:
C++标准程序库提供了三个迭代器相关辅助函数:advance(),distance(),iter_swap().前两个提供给所有的迭代器一些原本只有Random Access迭代器才有的能力:前进(或后退)多个元素,及处理迭代器之间的距离。第三个函数允许交换两个迭代器的值(交换的是迭代器所指的元素的内容)。


P321
所谓仿函数,是一个定义了operator()的对象
仿函数的优势:
1.仿函数比一般函数更灵巧,因为它可以拥有状态,事实上,对于仿函数,你可以同时拥有两个状态不同的实体,一般函数则不行。、
2.每个仿函数都有其类型。因此可以将仿函数的类型当做template参数来传递,从而指定某种行为模式,。此外还有一个好处,容器类型也会因仿函数的不同而不同。
3.执行速度上,仿函数通常比普通函数指针更快。

P327
for_each()有一个独门绝技,其他算法概莫有之,那就是可以返回其仿函数,这样, 你就可以通过for_each()的返回值来获取仿函数的状态。

P330
remove_if算法的实现版本:
template<class ForwIter ,class Predicate>
ForwIter std::remove_if(ForwIter beg,ForwIter end,Predicate op)
{
     beg=find_if(beg,end,op);
     if(beg==end)
          return beg;
     else
     {
          ForwIter  next=beg;
          return remove_copy_if(++next ,end,beg,op);
     }
}
从该实现可以看出,该算法先用find_if找出符合op的第一个元素,然后使用op的副本去处理剩余元素,所以,为了获得C++标准库的保证行为,你不应该传递一个“行为取决于被拷贝次数或被调用次数”的仿函数,要做到这一点,应当将operator()声明为const函数。

预定义的函数适配器
bind1st(op,value)           op(value,para);
bind2nd(op,value)           op(para,value);
not1(op)                !op(para)
not2(op)                !op(para1,para2)

成员函数的函数适配器
mem_fun_ref(op)      调用op,那是某对象的一个const 成员函数
mem_fun(op)           调用op,那是某对象指针的一个const 成员函数

mem_fun_ref会将原本“针对每个元素的函数调用动作”转为调用“被传递之成员函数”
问题在于for_each()会针对第三参数所传进来的指针,调用operator(),而不是调用该指针所指的成员函数,适配器mem_fun_ref将operator()调用动作做了适当的转换,因而解决了这个问题。
注意,被mem_fun_ref和mem_fun调用的成员函数必须是const 

用于一般函数身上的函数适配器
ptr_fun(op)      op(para)
                         op(para1,para2)
当需要仿函数(如not1等)而只有一般函数时,可用ptr_fun()来包裹一般函数传给not,或者需要绑定参数时也可用ptr_fun


P463
特殊容器
stack
     push()  top()  pop()  
queue
     front()  back()  push_back()  pop_front()
priority_queue
bit_set
     bitsets一个强有力的特征就是可以在整数值和位序列之间相互转换,只要很简单的产生一个临时bitset就可以办到:bitset<24>(27)


P501
string
     注意:当你打算检验搜寻函数find的返回值时,应该使用string::size_type类型而不是int 或unsigned。否则其与string::npos的比较将无法有效运行
如果索引超过实际字符数,搜寻函数会返回string::npos(表示没找到)
0 0