Effective STL-- 1 Container

1. 慎重选择容器

标准STL序列容器: vector, string, deque, list.

标准STL关联容器:set, multiset, map, multimap


vector<char> 作为string的替代

vector 作为标准关联容器的替代


2.不要试图编写独立于容器类型的代码

  class Widget{};
  typedef vector<Widget> WidgetContainer;
  typedef WidgetContainer::iterator WCIterator;
  WidgetContainer cw;
  Widget bestWidget;
  
  WCIterator = find(cw.begin(), cw.end(), bestWidget);

3. 确保容器中对象拷贝正确高效

  vector<Widget> vw;
  class SpecialWidget: public Widget{};
  SpecialWidget sw;
  vw.push_back(sw); //派生类特有部分在拷贝时被丢掉了

4. 调用empty 而不是检查size()是否为0

理由:empty对所有标准容器都是常数时间的操作,而对于一些list实现,size耗费线性时间。

list 不知道自己含有多少元素,求size需要线性遍历。

假如每次更新list时保持size更新,则那么list的更新链接过程就需要线性时间,为了使得list链接耗费常数实践,因此选择不实时保存size大小而通过遍历后获得。

5. 区间成员函数优先于与之对应的单元素成员函数

  v1.assign(v2.begin()+v2.size()/2, v2.end());//assign直接覆盖原有v1的值

  //区间创建
  container::container(InputIterator begin,//区间开始
                       InputIterator end);//区间结束
  //区间插入
  void container::insert(iterator position,
                         InputIterator begin,
                         InputIterator end);
  //区间删除 erase-remove方法
  iterator container::erase(iterator begin, iterator end);//指向被删除元素之后,存在性能大开销
  void container::erase(iterator begin, iterator end);
  //区间赋值
  void container::assign(InputIterator begin, InputIterator end);

6.当心C++编译器最烦人的分析机制

  //C++普遍规律 尽可能解释为函数声明
  ifstream dataFile("ints.dat");
  list<int> data(istream_iterator<int>(dataFile), istream_iterator<int>()); //分析为data函数参数为...

  list<int> data((istream_iterator<int>(dataFile)), istream_iterator<int>()); //加上括号表示为函数参数而非函数声明

  istream_iterator<int> dataBegin(dataFile);
  istream_iterator<int> dataEnd;
  list<int> data(dataBegin, dataEnd);
7.容器中元素new和delete需要对应

  void doSomething(){
    vector<Widget*> vwp;

    for(vector<Widget*>::iterator i = vwp.begin(); i!=vwp.end(); ++i)
    {
      delete *i;//new对应delete
    }
  }
  template<typename T>//函数子
    struct DeleteObject :public unary_function<const T*, void>{
    void operator()(const T* ptr) const
    {
      delete ptr;
    }
  };
  void doSomething(){
    vector<Widget*> vwp;

    for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>());//使用函数子来删除指针元素
  }
8. 切勿创建包含auto_ptr的容器对象

9. 慎重选择删除元素的方法

  Container<int> c;
  //对于连续内存的容器(vector, deque, string)
  c.erase(remove(c.begin(), c.end(), 1963), c.end());
  //对list
  c.remove(1973);
  //对于关联容器
  c.erase(1963);

  //判别式删除
  bool badValue(int);
  
  c.erase(remove_if(c.begin(), c.end(), badValue), c.end());//...
  c.remove_if(badValue);//list

  AssocContainer c;
  for(AssocContainer:iterator i=c.begin();i!=c.end(); )
  {
    if(badValue(*i)) c.erase(i++);//防止删除后产生迭代器失效
    else ++i;
  }

10. 了解分配子的约定和限制

11.

12.切勿对STL容器的线程安全性有不切实际的想法


你可能感兴趣的:(Effective STL-- 1 Container)