程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++ vector的用法小結

C++ vector的用法小結

編輯:關於C++

C++ vector的用法小結。本站提示廣大學習愛好者:(C++ vector的用法小結)文章只能為提供參考,不一定能成為您想要的結果。以下是C++ vector的用法小結正文


c++ vector用法

C++內置的數組支撐容器的機制,然則它不支撐容器籠統的語義。要處理此成績我們本身完成如許的類。在尺度C++中,用容器向量(vector)完成。容器向量也是一個類模板。

尺度庫vector類型應用須要的頭文件:#include <vector>。vector 是一個類模板。不是一種數據類型,vector<int>是一種數據類型。Vector的存儲空間是持續的,list不是持續存儲的。

1、 界說和初始化

vector< typeName > v1;       //默許v1為空,故上面的賦值是毛病的v1[0]=5;
vector<typeName>v2(v1); 或v2=v1;或vector<typeName> v2(v1.begin(), v1.end());//v2是v1的一個正本,若v1.size()>v2.size()則賦值後v2.size()被擴大為v1.size()。
vector< typeName > v3(n,i);//v3包括n個值為i的typeName類型元素
vector< typeName > v4(n); //v4含有n個值為0的元素
int a[4]={0,1,2,3,3}; vector<int> v5(a,a+5);//v5的size為5,v5被初始化為a的5個值。後一個指針要指向將被拷貝的末元素的下一名置。
vector<int> v6(v5);//v6是v5的拷貝
vector< 類型 > 標識符(最年夜容量,初始一切值);

2、 值初始化

1>     假如沒有指定元素初始化式,尺度庫自行供給一個初始化值停止值初始化。
2>     假如保留的式含有結構函數的類類型的元素,尺度庫應用該類型的結構函數初始化。
3>     假如保留的式沒有結構函數的類類型的元素,尺度庫發生一個帶初始值的對象,應用這個對象停止值初始化。

3、vector對象最主要的幾種操作

1. v.push_back(t)    在容器的最初添加一個值為t的數據,容器的size變年夜。
                     別的list有push_front()函數,在前端拔出,前面的元素下標順次增年夜。
2. v.size()        前往容器中數據的個數,size前往響應vector類界說的size_type的值。v.resize(2*v.size)或                  
v.resize(2*v.size, 99) 將v的容量翻倍(並把新元素的值初始化為99)
3. v.empty()     斷定vector能否為空
4. v[n]           前往v中地位為n的元素
5. v.insert(pointer,number, content)    向v中pointer指向的地位拔出number個content的內容。
                  還有v. insert(pointer, content),v.insert(pointer,a[2],a[4])將a[2]到a[4]三個元素拔出。
6. v.pop_back()    刪除容器的末元素,其實不前往該元素。
7.v.erase(pointer1,pointer2) 刪除pointer1到pointer2中央(包含pointer1所指)的元素。
                   vector中刪除一個元素後,此地位今後的元素都須要往前挪動一個地位,固然以後迭代器地位沒有主動加1,
                   然則因為後續元素的按序前移,也就相當於迭代器的主動指向下一個地位一樣。
8. v1==v2          斷定v1與v2能否相等。
9. !=、<、<=、>、>=      堅持這些操作符慣有寄義。
10. vector<typeName>::iterator p=v1.begin( ); p初始值指向v1的第一個元素。*p取所指向元素的值。
                    關於const vector<typeName>只能用vector<typeName>::const_iterator類型的指針拜訪。
11.   p=v1.end( ); p指向v1的最初一個元素的下一名置。
12.v.clear()      刪除容器中的一切元素。12.v.clear()      刪除容器中的一切元素。
#include<algorithm>中的泛函算法
搜刮算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()
分類排序:sort() 、merge()
刪除算法:unique() 、remove()
生成和變異:generate() 、fill() 、transformation() 、copy()
關系算法:equal() 、min() 、max()
sort(v1.begin(),vi.begin()+v1.size/2); 對v1的前半段元素排序
list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到則前往被查內容第一次湧現處指針,不然前往end()。
vector< typeName >::size_type x ; vector< typeName >類型的計數,可用於輪回好像for(int i)
初學C++的法式員能夠會以為vector的下標操作可以添加元素,其實否則:
vector<int> ivec;   // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
     ivec[ix] = ix; // disaster: ivec has no elements
上述法式試圖在ivec中拔出10個新元素,元素值順次為0到9的整數。然則,這裡ivec是空的vector對象,並且下標只能用於獲得已存在的元素。
這個輪回的准確寫法應當是:
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
     ivec.push_back(ix); // ok: adds new element with value ix
正告:必需是已存在的元素能力用下標操作符停止索引。經由過程下標操作停止賦值時,不會添加任何元素。僅能對確知已存在的元素停止下標操作  
  
4、內存治理與效力

      1.應用reserve()函數提早設定容量年夜小,防止屢次容量擴大操作招致效力低下。
        關於STL容器,最使人誇獎的特征之一就是是只需不跨越它們的最年夜年夜小,它們便可以主動增加到足以包容你放出來的數據。(要曉得這個最年夜值,只需挪用名叫max_size的成員函數。)關於vector和string,假如須要更多空間,就以相似realloc的思惟來增加年夜小。vector容器支撐隨機拜訪,是以為了進步效力,它外部應用靜態數組的方法完成的。在經由過程 reserve() 來請求特定年夜小的時刻老是按指數界限來增年夜其外部緩沖區。當停止insert或push_back等增長元素的操作時,假如此時靜態數組的內存不敷用,就要靜態的從新分派以後年夜小的1.5~2倍的新內存區,再把原數組的內容復制曩昔。所以,在普通情形下,其拜訪速度統一般數組,只要在從新分派產生時,其機能才會降低。正如下面的代碼告知你的那樣。而停止pop_back操作時,capacity其實不會由於vector容器裡的元素削減而有所降低,還會保持操作之前的年夜小。關於vector容器來講,假如有年夜量的數據須要停止push_back,應該應用reserve()函數提早設定其容量年夜小,不然會湧現很多次容量擴大操作,招致效力低下。
      reserve成員函數許可你最小化必需停止的從新分派的次數,因此可以免真分派的開支和迭代器/指針/援用掉效。但在我說明reserve為何可以那末做之前,讓我扼要引見有時刻使人迷惑的四個相干成員函數。在尺度容器中,只要vector和string供給了一切這些函數。
(1) size()告知你容器中有若干元素。它沒有告知你容器為它包容的元素分派了若干內存。
(2) capacity()告知你容器在它曾經分派的內存中可以包容若干元素。那是容器在那塊內存中總共可以包容若干元素,而不是還可以包容若干元素。假如你想曉得一個vector或string中有若干沒有被占用的內存,你必需從capacity()中減去size()。假如size和capacity前往異樣的值,容器中就沒有殘剩空間了,而下一次拔出(經由過程insert或push_back等)會激發下面的從新分派步調。
(3) resize(Container::size_type n)強迫把容器改成包容n個元素。挪用resize以後,size將會前往n。假如n小於以後年夜小,容器尾部的元素會被燒毀。假如n年夜於以後年夜小,新默許結構的元素會添加到容器尾部。假如n年夜於以後容量,在元素參加之前會產生從新分派。
(4) reserve(Container::size_type n)強迫容器把它的容量改成至多n,供給的n不小於以後年夜小。這普通強制停止一次從新分派,由於容量須要增長。(假如n小於以後容量,vector疏忽它,這個挪用甚麼都不做,string能夠把它的容量削減為size()和n中年夜的數,但string的年夜小沒有轉變。在我的經歷中,應用reserve來從一個string中修整過剩容量普通不如應用“交流技能”,那是條目17的主題。)
     這個簡介表現了只需有元素須要拔出並且容器的容量缺乏時就會產生從新分派(包含它們保護的原始內存分派和收受接管,對象的拷貝和析構和迭代器、指針和援用的掉效)。所以,防止從新分派的症結是應用reserve盡快把容器的容量設置為足夠年夜,最好在容器被結構以後連忙停止。
例如,假定你想樹立一個包容1-1000值的vector<int>。沒有應用reserve,你可以像如許來做:

vector<int> v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);

在年夜多半STL完成中,這段代碼在輪回進程中將會招致2到10次從新分派。(10這個數沒甚麼奇異的。記住vector在從新分派產生時普通把容量翻倍,而1000約等於210。)
把代碼改成應用reserve,我們獲得這個:

vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);

這在輪回中不會產生從新分派。
在年夜小和容量之間的關系讓我們可以預言甚麼時刻拔出將惹起vector或string履行從新分派,並且,可以預言甚麼時刻拔出會使指向容器中的迭代器、指針和援用掉效。例如,給出這段代碼,

string s;
...
if (s.size() < s.capacity()) {
s.push_back('x');
}

push_back的挪用不會使指向這個string中的迭代器、指針或援用掉效,由於string的容量包管年夜於它的年夜小。假如不是履行push_back,代碼在string的隨意率性地位停止一個insert,我們依然可以包管在拔出時代沒有產生從新分派,然則,與隨同string拔出時迭代器掉效的普通規矩分歧,一切從拔出地位到string開頭的迭代器/指針/援用將掉效。
回到本條目的宗旨,平日有兩情形應用reserve來防止不用要的從新分派。第一個可用的情形是當你確實或許年夜約曉得有若干元素將最初湧現在容器中。那樣的話,就像下面的vector代碼,你只是提早reserve恰當數目的空間。第二種情形是保存你能夠須要的最年夜的空間,然後,一旦你添加完整部數據,修整失落任何過剩的容量。
       2.應用“交流技能”來修整vector多余空間/內存
      有一種辦法來把它從已經最年夜的容量削減到它如今須要的容量。如許削減容量的辦法經常被稱為“壓縮到適合(shrink to fit)”。該辦法只需一條語句:vector<int>(ivec).swap(ivec);
表達式vector<int>(ivec)樹立一個暫時vector,它是ivec的一份拷貝:vector的拷貝結構函數做了這個任務。然則,vector的拷貝結構函數只分派拷貝的元素須要的內存,所以這個暫時vector沒有過剩的容量。然後我們讓暫時vector和ivec交流數據,這時候我們完成了,ivec只要暫時變量的修整過的容量,而這個暫時變量則持有了已經在ivec中的沒用到的多余容量。在這裡(這個語句開頭),暫時vector被燒毀,是以釋放了之前ivec應用的內存,壓縮到適合。
     3.用swap辦法強行釋放STL Vector所占內存

template < class T> void ClearVector( vector<T>& v )
{
    vector<T>vtTemp;
    vtTemp.swap( v );
}

    vector<int> v ;
    nums.push_back(1);
    nums.push_back(3);
    nums.push_back(2);
    nums.push_back(4);
    vector<int>().swap(v);
/* 或許v.swap(vector<int>()); */
/*或許{ std::vector<int> tmp = v;   v.swap(tmp);   }; //加年夜括號{ }是讓tmp加入{ }時主動析構*/

5、Vector 內存治理成員函數的行動測試

C++ STL的vector應用異常普遍,然則對其內存的治理模子一向有多種猜想,上面用實例代碼測試來懂得其內存治理方法,測試代碼以下:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> iVec;
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //1個元素, 容器容量為1
iVec.push_back(1);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //2個元素, 容器容量為2
iVec.push_back(2);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //3個元素, 容器容量為4
iVec.push_back(3);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //4個元素, 容器容量為4
iVec.push_back(4);
iVec.push_back(5);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //5個元素, 容器容量為8
iVec.push_back(6);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //6個元素, 容器容量為8
iVec.push_back(7);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //7個元素, 容器容量為8
iVec.push_back(8);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //8個元素, 容器容量為8
iVec.push_back(9);
cout << "容器 年夜小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //9個元素, 容器容量為16
/* vs2005/8 容量增加不是翻倍的,如 
  9個元素  容量9 
  10個元素 容量13 */
/* 測試effective stl中的特別的交流 swap() */
cout << "以後vector 的年夜小為: " << iVec.size() << endl;
cout << "以後vector 的容量為: " << iVec.capacity() << endl;
vector<int>(iVec).swap(iVec);
cout << "暫時的vector<int>對象 的年夜小為: " << (vector<int>(iVec)).size() << endl;
cout << "暫時的vector<int>對象 的容量為: " << (vector<int>(iVec)).capacity() << endl;
cout << "交流後,以後vector 的年夜小為: " << iVec.size() << endl;
cout << "交流後,以後vector 的容量為: " << iVec.capacity() << endl;
return 0;
}

6、vector的其他成員函數

c.assign(beg,end)
將[beg; end)區間中的數據賦值給c。
c.assign(n,elem)
將n個elem的拷貝賦值給c。
c.at(idx)
傳回索引idx所指的數據,假如idx越界,拋出out_of_range。
c.back()
傳回最初一個數據,不檢討這個數據能否存在。
c.front()
傳回地一個數據。
get_allocator
應用結構函數前往一個拷貝。
c.rbegin()
傳回一個逆向隊列的第一個數據。
c.rend()
傳回一個逆向隊列的最初一個數據的下一個地位。
c.~ vector <Elem>()
燒毀一切數據,釋放內存。  

以下是其它網友的彌補:

1 、根本操作

(1)頭文件#include<vector>.

(2)創立vector對象,vector<int> vec;

(3)尾部拔出數字:vec.push_back(a);

(4)應用下標拜訪元素,cout<<vec[0]<<endl;記住下標是從0開端的。

(5)應用迭代器拜訪元素.

vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
  cout<<*it<<endl;

(6)拔出元素:    vec.insert(vec.begin()+i,a);在第i+1個元素後面拔出a;

(7)刪除元素:    vec.erase(vec.begin()+2);刪除第3個元素

vec.erase(vec.begin()+i,vec.end()+j);刪除區間[i,j-1];區間從0開端

(8)向量年夜小:vec.size();

(9)清空:vec.clear();

2、vector的元素不只僅可使int,double,string,還可所以構造體,然則要留意:構造體要界說為全局的,不然會失足。上面是一段冗長的法式代碼:

#include<stdio.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;

typedef struct rect
{
 int id;
 int length;
 int width;

  //關於向量元素是構造體的,可在構造體外部界說比擬函數,上面依照id,length,width升序排序。
  bool operator< (const rect &a) const
 {
  if(id!=a.id)
   return id<a.id;
  else
  {
   if(length!=a.length)
    return length<a.length;
   else
    return width<a.width;
  }
 }
}Rect;

int main()
{
 vector<Rect> vec;
 Rect rect;
 rect.id=1;
 rect.length=2;
 rect.width=3;
 vec.push_back(rect);
 vector<Rect>::iterator it=vec.begin();
 cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl; 

return 0;

}

3  算法

(1) 應用reverse將元素翻轉:須要頭文件#include<algorithm>

reverse(vec.begin(),vec.end());將元素翻轉(在vector中,假如一個函數中須要兩個迭代器,

普通後一個都不包括.)

(2)應用sort排序:須要頭文件#include<algorithm>,

sort(vec.begin(),vec.end());(默許是按升序分列,即從小到年夜).

可以經由過程重寫排序比擬函數依照降序比擬,以下:

界說排序比擬函數:

bool Comp(const int &a,const int &b)
{
    return a>b;
}

挪用時:sort(vec.begin(),vec.end(),Comp),如許就降序排序。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved