条款三十二
若要删除元素,在remove一类算法后使用erase
删除元素
remove并不能做到真的移除元素,只是把需要remove的元素使用之后应当留下的元素进行填充,然后返回一个迭代器指向第一个应当被移除的元素的位置或end()
remove_if和unique同理
故使用erase(remove(begin(),end(),val), end());
条款三十三
对指针容器慎用remove
这里指的的内置指针,现在你必定不会想要用一个内置指针数组,毕竟有智能指针的存在,甚至连裸指针都不想用。
因为remove会使用后面元素的值来覆盖前面的元素的值,也就意味着被覆盖的指针将会永远失去,无法再删除这些指针的内存(如果你没有备份的话),故需要先delete这些指针再remove,或者remove_if来做这么个奇怪的活儿。
条款三十四
使用排序区间的算法
使用二分查找的:
binary_search lower_bound upper_bound equal_range
对数时间(随机访问容器)
线性时间(非随机访问),但比较次数任然是对数级
set_union set_intersection set_difference set_symmetric_difference
线性时间
归并 merge 原地归并inplace_merge
线性时间
include
线性时间
unique unique_copy
除去连续重复的元素,非连续不会被除去,故通常用在排序区间,不过其实相同元素连在一起但是非有序也可。
最后注意一点,用于排序的比较函数应当和用于查找的比较函数保持一致,才不会违反人的直觉。
条款三十五
mismatch与lexicographical_compare
misatch(begin(), end(), s2.begin(), 条件);
s1.size() <= s2.size()是前提
返回一对迭代器分别指向s1,s2中对应位置不符条件的元素
若s1,s2相等,则返回两容器end(),若s1.size()?<s2.size(),则返回s1.end()与s2的某个迭代器指向相应元素。
lexicographical_compare(s1.begin(),s1.begin(),s2.begin(),s2.end(),条件);
若按字典序s1<s2则返回true
条件均为二元谓词,均有默认版本,misatch基于equal_to即相等,lexicographical_compare基于less,即等价。
条款三十六
copy_if的正确实现
啊,那么这玩意儿已经有了
不能使用remove_copy_if(begin(),end(),s2.begin(),not1(p));
来实现copy_if,虽然看起来意思一样。
但是not1(ptr_fun(p));才正确,然而这要求p是个可配接的函数对象,故自写循环实现(实际上copy_if实现也确实是个简单循环,和其他很多。)
条款三十七
accumulate或for_each进行区间统计
使用带数据成员的含数子就可以使用for_each或accumulate来实现某些统计
accumulate会返回总和,或根据用户定义的函数的t类型值来返回相应值
for_each则会返回使用的函数子。
条款三十八
按照值传递的方式来设计函数子
即函数子不应当拥有虚函数,因为函数子总是作值传递,会引起裁切。这也限制函数子不应当拥有大量数据成员以避免过长时间的含数子复制。如果你希望函数子拥有这两者,那么就用另一个类实现,然后放个指针到函数子里
条款三十九
确保判别式为纯函数
纯函数的返回值仅仅依赖于其参数和常量,这使得用相同的参数调用它会返回一样的结果。
这一条款是因为使用的算法会复制函数子(有些甚至每个循环都用新创建的),这使得改变会作用于一个副本而不是本体,也使得之后再使用这个函数子产生不想要的结果,避免这点可以从operator() const开始。
条款四十
若一个类是函数子,则使得它可配接
让函数子继承
unary_function<参数,返回值>
binary_function<参数1,参数2,返回值>
可使得函数子可配接
参数为传值或引用时直接写入参数本身类型,忽略const与&;参数为指针时写入与参数完全一致的类型。