《Effective STL》读书笔记十二:算法

来源:互联网 发布:触摸屏编程什么意思 编辑:程序博客网 时间:2024/06/05 16:50
Item 30:确保操作的目标区间足够大
Make sure destination ranges are big enough
  • 下面算法的使用是有bug的:
int transmogrify(int x); // this function produces some new value from x
vector<int> values;
vector<int> results;
transform( values.begin(), values.end(), results.end(), transmogrify);
正确的使用方法是:
vector<int> results; 
transform( values.begin(), values.end(), back_inserter(results), transmogrify);
  • 下面的代码是错误的:
vector<int> values;
vector<int> results; 
results.reserve(results.size() + values.size());
transform( values.begin(), values.end(), results.end(), transmogrify);
在上面的代码中,对未被初始化的内存赋值是不正确的,因为赋值只在两个对象之间进行才是有意义的。而且,这样的操作之后,容器的size()操作和end()操作都会返回错误的值。
可以使用如下的正确的代码:
vector<int> values;
vector<int> results;
if ( results.size() < values.size()){
  results.resize(values..size());
}
transform(values.begin(), values.end(), results.begin(), transmogrify);

Item 31:了解你拥有的排序的选择
Know your sorting options
  • 当需要排序时,可以考虑以下几个算法:partition, stable_partition, nth_element, partial_sort, sort, stable_sort
Item 32:如果你真的想删除的话,在remove-like的算法后紧接上erase
Follow remove-like algorithms by erase if you really want to remove something
  • 由于从容器中删除一个元素的唯一方法是调用容器的成员方法,而remove不知道它所操作的容器类型,因此remove不能在一个容器中删除元素。
  • 如果你真的想删除的话,在remove-like的算法后紧接上erase:v.erase(remove(v.begin(), v.end(), 99), v.end())。
  • list的remove成员函数跟remove算法不太一致,它会真正的删除元素。
  • 另外两个remove-like算法跟remove的用法一致:remove_if和unique
  • 为了更好的理解remove操作后的容器,可以参考remove的一种可能的实现方法:
template < class ForwardIterator, class T >
  ForwardIterator remove ( ForwardIterator first, ForwardIterator last, const T& value )
{
  ForwardIterator result = first;
  for ( ; first != last; ++first)
    if (!(*first == value)) *result++ = *first;
  return result;
}

Item 33:对指针容器的remove-like算法保持谨慎
Be wary of remove-like algorithms on containers of pointers
  • 在指针容器上进行remove-like算法时,由于removed的指针会被覆盖,会导致出现内存泄露。
  • 为了防止内存泄露,可以使用partition算法替代remove-like算法,或者使用智能指针。
Item 34:注意哪些算法需要排序的区间
Note which algorithms expect sorted ranges
  • 需要在已排序的区间上进行操作的算法包括:binary_search, lower_bound, upper_bound, equal_range, set_union, set_intersection, set_difference, set_symmetric_difference, merge, inplace_merge, includes
  • 这些算法所使用的比较函数必须跟排序时所使用的排序函数是一致的。
Item 37:使用accumulate或者for_each来对区间进行概括总结
Use accumulate or for_each to summarize ranges
  • for_each和accumulate主要存在两点区别:一是accumulate名字就意味着它是为了生成一个区间内的概述,而for_each只是意外着你想对区间内的每一个元素进行某些操作;第二个区别在于accumulate直接返回总结值,而for_each返回一个函数对象