C++——vector超詳細介紹

vector:

vector是表示可變大小數組的序列容器。即動態順序表。

 就像數組一樣,vector也採用的連續存儲空間來存儲元素。也就是意味着可以採用下標對vector的元素進行訪問,和數組一樣高效。但是又不像數組,它的大小是可以動態改變的,而且它的大小會被容器自動處理。 

相關接口:

構造函數:

  • vector() 無參構造
  • vector(size_type n, const value_type& val = value_type()) 構造並初始化n個val
  • vector (const vector& x); 拷貝構造
  • vector (InputIterator first, InputIterator last); 使用迭代器進行初始化構造

迭代器:

  • iterator的使用 接口說明
  • begin() 獲取第一個數據位置的iterator
  • end() 獲取最後一個數據的下一個位置的iterator
  • rbegin() 獲取最後一個數據位置的reverse_iterator
  • rend() 獲取第一個數據前一個位置的reverse_iterator
  • cbegin() 獲取第一個數據位置的const_iterator
  • cend() 獲取最後一個數據的下一個位置的const_iterator

容量空間:    每次擴容50%

  • size() 獲取數據個數
  • capacity() 獲取容量大小
  • empty() 判斷是否爲空
  • void resize (size_type n, value_type val = value_type()); 改變vector的size
  • void reserve (size_type n); 改變vector放入capacity      

vector增刪查改:

  • void push_back (const value_type& val); 尾插
  • void pop_back(); 尾刪
  • InputIterator find (InputIterator first, InputIterator last, const T& val);     查找。(注意這個是算法模塊實現,不是 vector的成員接口)
  • iterator insert (iterator position, const value_type& val);  在position之前插入val
  • iterator erase (iterator position); 刪除position位置的數據
  • void swap (vector& x); 交換兩個vector的數據空間
  • reference operator[] (size_type n); 像數組一樣訪問

vector 迭代器失效問題:也是push_back()的缺陷

兩層含義:

1. 無法通過迭代器++,--操作遍歷整個stl容器。記作:第一層失效。

2. 無法通過迭代器存取迭代器所指向的內存。 記作:第二層失效。

vector迭代器的幾種失效的情況:  push_back()的缺陷:

  • 當插入(push_back)一個元素後,end操作返回的迭代器肯定失效。  
  • 當插入(push_back)一個元素後,capacity返回值與沒有插入元素之前相比有改變,則需要重新加載整個容器,此時first和end操作返回的迭代器都會失效。  
  • 當進行刪除操作(erase,pop_back)後,指向刪除點的迭代器全部失效;指向刪除點後面的元素的迭代器也將全部失效。

insert/erase導致的迭代器失效:

// insert/erase導致的迭代器失效 
#include <iostream> 
#include <algorithm> 
#include <vector> using namespace std;
 
int main() {    
    int a[] = { 1, 2, 3, 4 };    
    vector<int> v(a, a + sizeof(a) / sizeof(int));
 
    // 使用find查找3所在位置的iterator    
    vector<int>::iterator pos = find(v.begin(), v.end(), 3);
 
    // 刪除pos位置的數據,導致pos迭代器失效。    
    v.erase(pos);    
    cout << *pos << endl; // 此處會導致非法訪問
 
    // 在pos位置插入數據,導致pos迭代器失效。    
    // insert會導致迭代器失效,是因爲insert可    
    // 能會導致增容,增容後pos還指向原來的空間,而原來的空間已經釋放了。    
    pos = find(v.begin(), v.end(), 3); 
    v.insert(pos, 30);    
    cout << *pos << endl; // 此處會導致非法訪問
    return 0; 
}

vetor使用了連續分配的內存,安插操作時:

  1. 容器還有一定的容量(v.capacity())來容納這個元素。如此一來,安插和移除操作不會因容器滿而重新分配內存。在安插和移除操作後,作用點位置前的元素並沒改變,而操作位置後的元素向後或向前移動一位。
  2. 插入元素後當發現開闢的空間不夠了,就會開闢更大的空間來進行拷貝數據,這個時候原來的start、finish、endofstorage都會發生變化,所以要插入位置已經變化,而傳過來的位置還是原來的位置,就會出現插入越界。

刪除操作時:

erase迭代器失效是在刪除一個元素的時候,後面的元素要向前挪動,所以迭代器指向的位置就會被前面的覆蓋,這時候++迭代器,就會跳過刪除元素的後一個。

解決迭代器失效方法:

刪除解決:<此部分代碼來源網絡>


for (iter = cont.begin(); iter != cont.end();)
{
   (*it)->doSomething();
   if (shouldDelete(*iter))
      iter = cont.erase(iter);  //erase刪除元素,返回下一個迭代器
   else
      ++iter;
}

erase方法可以返回下一個有效的iterator。這樣刪除後iter指向的元素後,返回的是下一個元素的迭代器,這個迭代器是vector內存調整過後新的有效的迭代器。

插入處理:<此部分代碼來源網絡>

我們在插入前計算出相對與start的相對距離,那麼當插入時候我們用計算的距離還原pos進行插入。

Iterator Insert(Iterator position, const T& value)
    {

        assert(position < End() && position >= Begin());
        size_t off = position - start;
        if (finish == endofstorage)
        {
            Expand(Capacity() * 2);
        }

        position = off + start; // 注意跌掉器失效
        for (Iterator i = End(); i != position; --i)
        {
            *i = *(i - 1);
        }
        *position = value;
        ++finish;
        return position;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章