您的位置:首页 > 编程语言 > C语言/C++

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

2014-04-05 21:07 260 查看
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(表示没找到)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: