C++ STL — 第6章 STL容器(一)vector

6.1 容器的共通能力和共通操作

  所有容器提供的都是value語意而非reference語意。容器元素必須能夠被拷貝。

  總體而言,所有元素形成一個次序。運用迭代器遍歷,也是算法的基礎。

 

  各項操作並非安全,調用者必須確保參數符合要求。違反可能導致未定義行爲。通常STL自身不拋出異常。


  初始化:每個容器提供了一個默認構造函數、copy構造函數、析構函數。

  容器類別的共通函數:

  C c;  不含任何元素的空容器

  C c(c1);   產生一個同型容器

  C c(beg, end);   複製區間元素,作爲容器初值

  c.~C();   刪除所有元素,釋放內存

  c.size();  返回容器元素數量

  c.empty();  若容器爲空返回true

  c.max_size();  返回容器內元素最大可能數量

  c1 == c2 ;   

  c1 != c2 ;   >  <  >=  <=

  c1 = c2;  將c2的所有元素賦值給c1

  c1.swap(c2);  交換c1和c2的數據

  swap(c1, c2);  同上,全局函數

  c.begin();   返回指向第一個元素迭代器

  c.end();  返回指向最後元素的下個位置的迭代器

  c.rbegin();  返回指向逆向遍歷時候的第一個元素的逆向迭代器

  c.rend();  返回指向逆向遍歷時候的最後元素的下個位置的逆向迭代器

  c.insert(pos, elem);  將elem的一份副本插入pos處,返回值和pos意義並不同

  c.erase(beg, end);  移除區間內所有元素

  c.clear();   移除所有元素

  c.get_allocator();  返回容器的內存模型


  以另一個容器的元素爲初值完成初始化:

  list<int> l;

  vector<float> c(l.begin(), l.end());


  以某個數組元素爲初始初始化:

  int a[] = { 2, 3, 17, 33, 45, 77 };

  set<int> c(a, a + sizeof(a)/sizeof(*a));


  標準輸入完成初始化:

  deque<int> c((istream_iterator<int>(cin)),(istream_iterator<int>()));  //括號不能少,否則視爲c爲一個函數聲明



6.2 vector : 動態數組

  #include <vector>

  具備assignable 和 copyable兩個性質

  namespace std {

template <class T, class Allocator = allocator<T> >

class vector;  

  }

  //第二個參數一般省略,缺省是C++ STL提供的allocator分配器


  vector是有序羣集,支持隨機存取,隨機存取迭代器,任何STL算法都適用。

  末端附加和刪除元素時候,性能好。前端或中間插入和刪除元素性能不好。因爲要移動操作點之後的所有元素,這是很多 = 賦值操作符。

  capacity(); 返回vector實際能容納的元素數量,如果超越這個數量vector就會重新配置內部存儲器。

  一旦內存重新配置,和vector元素有關的所有reference、pointers、iterator都會失效,內存重新配置很耗時間。

  可以使用reserve()函數保留適當容量,只能增不能減,避免總是重新配置內存,避免iterator失效。 vector<int> v;   v.reserve(80);  分配了80個元素的v

  還可以在構造期間分配大小:  vector<int> v(100);  //v 起始大小100個元素


  構造和析構函數:

  vector<Elem> c;

  vector<Elem> c1(c2);

  vector<Elem> c(n);

  vector<Elem> c(n, elem);

  vector<Elem> c(beg, end);

  c.~vector<Elem>();


  非變動性操作:

  c.size();

  c.empty();

  c.max_size();

  capacity();

  reserve(n);

  c1 ==  c2; !=  <  >  <=   >=


  賦值:

  c1 = c2;

  c.assign(n, elem);

  c.assign(beg, end);

  c1.swap(c2);

  swap(c1, c2);


  元素存取:index 從0到size()-1; 對於non-const vector返回元素的reference;程序員自己檢查範圍例如是否爲空;

  c.at(idx);  //out_of_range 異常

  c[idx];  不進行範圍檢查

  c.front();

  c.back();


  迭代器相關:其實就是個指針,vector內部結構是數組

  c.begin();  //隨機存取迭代器

  c.end();

  c.rbegin();  //逆向迭代器

  c.rend();


  迭代器失效情況:較小的索引位置插入或移除元素;容量變化重新引起內存分配

  插入和移除元素使作用點之後的元素迭代器失效,甚至引發內存重新分配屆時所有迭代器失效;


  移除插入相關操作:

  c.insert(pos, elem);  //返回新元素位置

  c.insert(pos, n, elem);  //無返回值

  c.insert(pos, beg, end);  //無返回值

  c.push_back(elem); 

  c.pop_back();

  c.erase(pos); //返回下一個元素的位置

  c.erase(beg, end);  //返回下一個元素的位置

  c.resize(num);  將元素數量改爲num,如果size()增大了,多出新元素需要默認構造函數完成

  c.resize(num, elem);

  c.clear();  容器清空


  vector<Elem> c;

  c.erase(remove(c.begin(), c.end(), val), c.end());  //將所有其值爲val的元素移除 

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
 
using namespace std;
 
int main()
{
    int a[] = {3, 4, 5, 3, 7, 9, 3, 4};
    vector<int> v(a, a+sizeof(a)/sizeof(*a));
    v.erase(remove(v.begin(), v.end(), 3), v.end());
 
    print_elements(v, "after erase: "); //4 5 7 9 4
    return 0;
}

若想移除與某值相等的第一個元素:

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
 
using namespace std;
 
int main()
{
    int a[] = {3, 4, 5, 3, 7, 9, 3, 4};
    vector<int> v(a, a+sizeof(a)/sizeof(*a));
    vector<int>::iterator pos = find(v.begin(), v.end(), 3);
    if(pos != v.end())
    {
        v.erase(pos);
    }
    print_elements(v, "after erase: "); //4 5 3 7 9 3 4
    return 0;
}

將vector當作一般array使用:

&v[i] = &v[0] + i;

vector<char> v;

v.resize(40);

strcpy(&v[0], "hello, world");

printf("%s\n", &v[0]);  //printf("%s\n", v.begin()); is error


異常處理:

下標操作的安全版本:at()

push_back()安插元素時候發生異常,插入不起作用

若元素拷貝不拋出異常,insert要麼成功要麼不生效

pop_back()不拋異常

若拷貝操作不拋異常,erase()和clear()不拋異常

swap()不拋異常

若拷貝操作絕對不拋異常,那麼所有操作要麼成功要麼不起作用。

析構函數不拋異常


一個例子總結vector:

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
#include <string>
 
using namespace std;
 
int main()
{
    vector<string> s;
    s.reserve(5);
 
    s.push_back("Hello, ");
    s.push_back("how ");
    s.push_back("are ");
    s.push_back("you ");
    s.push_back("?");
 
    print_elements(s, "init: ");  //init: Hello,  how  are  you  ?
 
    cout << "max_size(): " << s.max_size() << endl;  //1073741823
    cout << "size(): " << s.size() << endl;  //5
    cout << "capacity(): " << s.capacity() << endl; //5
 
    swap(s[1], s[3]);
    s.insert(find(s.begin(), s.end(), "?"), "always");
 
    s.back() = "!";
 
    print_elements(s, "after: ");  //after: Hello,  you  are  how  always !
 
    cout << "max_size(): " << s.max_size() << endl;  //1073741823
    cout << "size(): " << s.size() << endl;   //6
    cout << "capacity(): " << s.capacity() << endl;  //10
    return 0;
}


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