C++标准程序库(学习笔记)三
2014-04-05 21:07
375 查看
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(表示没找到)
当你对着容器赋值元素时,源容器的所有元素被拷贝到目标容器中,后者原本所有的元素全部被移除,所以容器的赋值代价比较高昂
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(表示没找到)
相关文章推荐
- c语言字符串库函数#include<string.h>
- C++ 文件IO
- c语言字符类别测试库函数#include<ctype.h>
- c++ vector的用法,以及二维数组的传递和返回
- OC语言自学《九》---- OC(面向对象)
- C++随机函数
- 两个数交换算法(不需要临时变量)
- 在C++中的详细说明
- C++中几个重要的关键字总结
- [ZZ]c++ cout 格式化输出浮点数、整数及格式化方法
- C++中地图的使用
- c语言之extern关键字
- c++的一些默认函数
- 陈正冲老师讲c语言之声明和定义的区别
- sprintf函数的使用
- 陈正冲老师讲c语言之const关键字
- 陈正冲老师讲c语言void关键字
- 点led灯(进阶)——c语言
- 对输入内容的识别
- C++面试题(1)