STL序列式容器之vector

一、概述

vector構造出一個動態數組,本身是將元素置於動態數組中加以管理的抽象概念。使用vector之前必須含入頭文件<vector>,vector是一個定義於namespace std內的template

namespace std {
    template <class T,
              class Allocator = allocator<T> >
    class vector;
}

vector將元素複製到內部動態數組中,vector的迭代器是隨機存取迭代器,所以支持隨機存取。在末端添加、刪除元素時,vector的性能相當好。但是在前端或者中部安插或刪除元素,性能就不怎麼好了,因爲操作點之後的每一個數據都要移動到另一個位置。vector性能優異的重要原因就是配置比其容納元素所需更多的內存。vector的容量很重要
    1. 一旦內存重新配置,和vector相關的引用、指針、迭代器都會失效;
    2. 內存重新配置很耗時間。

二、vector的內部結構

vector類內通過三個保護成員的迭代器變量維護內存空間的使用:

template <class T, class Alloc = alloc>
class vector {
//省略其他成員
protected:
    iterator start;            //表示目前使用空間的頭
    iterator finish;           //表示目前使用空間的尾
    iterator end_of_storage;   //表示目前可用空間的尾
}

新增加元素時,如果超過當時容量,則容量會擴充至兩倍。如果兩倍容量仍然不夠,就擴張至足夠大的容量。所謂動態增加大小,並不是在原空間之後接續新空間(因爲無法保證原空間之後有可用空間),而是以原大小的兩倍另外配置一塊較大的空間,然後將原空間內容拷貝過來,然後在原內容之後構造新元素,釋放原空間。一旦引起空間重新配置,指向原空間的所有迭代器就失效了!

三、vector的操作函數

1. 構造、拷貝和析構

操作 效果
vector<Elem> c 產生一個存放Elem類型元素的空vector
vector<Elem> c1(c2) 產生一個與c2同型的vector,每個元素都被複制
vector<Elem> c(n) 產生一個含有n個元素,以default構造函數產生元素的vector
vector<Elem> c(n,elem) 產生一個含有n個elem元素的vector
vector<Elem> c(beg,end) 產生一個以區間[beg,end]內元素爲初值的vector
c.~vector<Elem>() 銷燬所有元素,釋放內存


2. 非變動性操作

操作 效果
c.size() 返回元素個數。
c.empty() 判斷容器大小是否爲0。
c.max_size() 返回整個內存空間可容納元素最大數量
c.capacity() 返回重新分配空間前容器所能容納的元素最大數量
c.reserve() 如果容量不足則擴大之
c1 == c2 判斷c1是否等於c2
c1 != c2 判斷c1是否不等於c2
c1 < c2 判斷c1是否小於c2
c1 > c2 判斷c1是否大於c2
c1 <= c2 判斷c1是否小於等於c2
c1 >= c2 判斷c1是否大於等於c2


3. 賦值操作

操作 效果
c1 = c2 將c2的全部元素賦值給c1。
c.assign(n,elem) 將elem的n個拷貝賦值給c。
c.assign(beg,end) 將區間[beg,end]的元素賦值給c
c1.swap(c2) 將c1和c2元素互換
swap(c1,c2) 同上,此爲全局函數


4. 元素存取操作
按照C和C++的慣例,第一元素的索引爲0,最後一個元素的索引爲size()-1。

操作 效果
c.at(idx) 返回索引位置idx處的元素,如果idx越界,拋出out_of_range異常
c[idx] 返回索引位置idx處的元素,不進行範圍檢查
c.front() 返回第一個元素,不檢查元素是否存在
c.back() 返回最後一個元素,不檢查元素是否存在


5. 迭代器函數

操作 效果
c.begin() 返回一個隨機存取迭代器,指向第一個元素
c.end() 返回一個隨機存取迭代器,指向最後一個元素的下一位置
c.rbegin() 返回一個逆向迭代器,指向逆向迭代的第一個元素
c.rend() 返回一個逆向迭代器,指向逆向迭代的最後元素的下一位置


6. 安插和移除元素

操作 效果
c.insert(pos,elem) 在pos位置插入一個elem副本,返回新元素的位置
c.insert(pos,n,elem) 在pos位置插入n個elem副本,無返回值
c.insert(pos,beg,end) 在pos位置插入區間[beg,end]內的元素,無返回值
c.push_back(elem) 在尾部添加一個elem的副本
c.pop_back() 移除最後一個元素,不回傳
c.erase(pos) 移除pos位置所指元素,返回下一元素的位置
c.erase(beg,end) 移除區間[beg,end]內的元素,返回下一元素的位置
c.resize(num) 將大小改爲num。如果size增長了,新增大小以default構造函數產生出來
c.resize(num,elem) 將大小改爲num。如果size增長了,新增大小以elem副本產生出來
c.clear() 移除所有元素,將容器清空


如果要移除與某值相等的所有元素,可以這麼做:

std::vector<Elem> coll;
'''
// remove all elements with value val
std::vector<Elem>::iterator pos;
coll.erase(remove(coll.begin(),coll.end(),val), coll.end());

如果要移除與某值相等的第一個元素,可以這麼做:

std::vector<Elem> coll;
'''
// remove first element with value val
std::vector<Elem>::iterator pos;
pos = find(coll.begin(),coll.end(),val);
if (pos != coll.end()) {
    coll.erase(pos);
}

四、Class vector<bool>

C++標準程序庫專門爲bool型的vector設計了一個特殊版本,目的是獲取一個優化的vector。其耗用空間遠遠小於一般vector。一般vector會爲每個元素至少分配一個byte空間,而vector<bool>內部只會用一個bit來存儲一個元素。不過C++的最小尋址單元通常以byte爲單位,因此vector<bool>::iterator並不返回真正的隨機存取迭代器。此外vector<bool>會比一般vector慢一點,因爲所有元素操作都轉化爲位操作。因爲vector<bool>的大小可以動態改變,所以可以作爲bitfield(位域),由此可以添加或刪除bits。若需要靜態大小的bitfield,應當使用bitset。

vector<bool>的特殊操作

操作 效果
c.flip() 將所有bool元素取反值
m[idx].flip() 將索引idx位置處的bit元素取反值
m[idx] = val 令索引idx位置處的bit元素值爲val
m[idx1] = m[idx2] 令索引idx1的bit元素值爲索引idx2的bit元素值

五、程序示例

vector的使用示例

//example of vector
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
    vector<string> sentence;

    sentence.reserve(5);

    sentence.push_back("Hello,");
    sentence.push_back("how");
    sentence.push_back("are");
    sentence.push_back("you");
    sentence.push_back("?");

    copy(sentence.begin(), sentence.end(),
        ostream_iterator<string>(cout, " "));
    cout << endl;

    //max_size()返回當前整個內存空間可以容納string類型數據總量
    cout << "max_size(): " << sentence.max_size() << endl;
    cout << "size(): " << sentence.size() << endl;
    cout << "capacity(): " << sentence.capacity() << endl;

    swap(sentence[1], sentence[3]);

    sentence.insert(find(sentence.begin(), sentence.end(), "?"),
        "always");
    sentence.back() = "!";

    copy(sentence.begin(), sentence.end(),
        ostream_iterator<string>(cout, " "));
    cout << endl;

    cout << "max_size(): " << sentence.max_size() << endl;
    cout << "size(): " << sentence.size() << endl;
    cout << "capacity(): " << sentence.capacity() << endl;

    return 0;
}

輸出結果:
這裏寫圖片描述

vector<bool>的使用示例

#include<vector>
#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;

int main()
{
    vector<bool> vec1;
    vector<int> vec2;

    cout << vec1.max_size() << endl;
    cout << vec2.max_size() << endl;

    vec1.push_back(true);
    vec1.push_back(1);
    vec1.push_back(false);
    vec1.push_back(0);

    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    vec1.flip();  //所有位置取反
    vec1.at(0) = 1;
    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    vec1[1] = vec1[0];
    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    cout << "vec1.size:" << vec1.size() << ", " << "vec1.capacity:" << vec1.capacity() << endl;
    cout << "sizeof vec1:" << sizeof(vec1) << endl;  //24

    vec1.push_back(false);
    vec1.push_back(0);
    cout << "sizeof vec1:" << sizeof(vec1) << endl;  //24,說明與元素個數無關,僅與其內部結構相關

    return 0;
}

輸出結果:
這裏寫圖片描述

發佈了37 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章