1. 程式人生 > >STL進階--vector vs deque

STL進階--vector vs deque

可能 cati orm real cap als 可用性 () code

vector

  class Dog;
// 例 1:
  vector<Dog> vec(6);  // vec.capacity() == 6, vec.size() == 6, 
                       // 默認構造生成6 Dogs

// 例 2:
  vector<Dog> vec; // vec.capacity() >= 0, vec.size() == 0
  vec.resize(6);   // vec.capacity() >= 6, vec.size() == 6, 
                   // 默認構造生成6 Dogs

// 例 3:
  vector<Dog> vec;
  vec.reserve(6);   // vec.capacity() >= 6, vec.size() == 0, 
                    // 不調用默認構造

// vector容量指數型增長,用完之後會重新分配,拷貝元素
/*
 * 避免重新分配內存的策略:
 * 1. 如果所需的最大元素個數已知, reserve(MAX);
 * 2. 如果不知道,先reserve盡可能多,等所有元素插入完畢,再將剩余的切除。
 */

deque

/*
 * - 沒有重新分配 
 *   deque沒有reserve()和capacity()
 * - 比vector稍慢,因為數據結構比vector復雜,因為不連續定位也有一定的開銷,更多的cache miss或page fault
 * - 現代編譯器往往會把他們放到一起
 */

//固定大小線性增長

如何選擇

一般原則

- 經常需要在前面插入的?  -> deque
- 性能重要的?   -> vector

詳細分析

  1. 元素類型
    • 如果不是很小的類型,那麽deque相比vector並不會低效很多
  2. 內存的可用性
    • 大塊的連續內存分配是否可能成為問題,內存受限
  3. 數據增長是否不可預期

      vector<int> vec;
      for (int x=0; x<1025; x++) 
         vec.push_back(x);   // 11 reallocations performed (growth ratio = 2)
    
            //   workaround: reserve()
    
  4. 因為增長帶來的指針/引用/叠代器失效

      vector<int> vec = {2,3,4,5}; 
      int* p = &vec[3]
      vec.push_back(6);
      cout << *p << endl;  // 未定義的行為
    
      deque<int> deq = {2,3,4,5};
      p = &deq[3];
      deq.push_back(6);
      cout << *p << endl;  // OK
      // push_front()也OK
      // deque: 在首尾插入不會使指針失效
    
    // 註:在中間插入刪除的話,還是會使指針失效
  5. vector獨有的特性: 兼容C

      vector<int> vec = {2,3,4,5}; 
    
      void c_fun(const int* arr, int size);
    
      c_fun(&vec[0], vec.size());
    
      // 對於其他容器,需要先將數據拷貝到vector
      list<int> mylist;
      ...
      vector<int> vec(mylist.gegin(), mylist.end());
      c_fun(&vec[0], vec.size());
    
      // 註: &vector[0]可以當做C的數組使用
      // 一個例外是: vector<bool>
      void cpp_fun(const bool* arr, int size);
      vector<bool> vec = {true, true, false, true}; 
      cpp_fun(&vec[0], vec.size()); // vector<bool>的每個元素優化為由1bit來表示,可以用vecter<int>或者bitset

總結

  1. 經常push_front() - deque
  2. 高性能 - vector
  3. 不是細小的數據類型 - deque
  4. 內存受限 - deque
  5. 不可預期的增長 - deque
  6. 指針有效性 - deque
  7. C接口 - vector

STL進階--vector vs deque