1. 程式人生 > 其它 >vector insert_C++ vector用法詳解

vector insert_C++ vector用法詳解

技術標籤:vector insertvector 刪除指定元素vector函式reversevector刪除第i個元素

vector概述

  vector是種容器,類似陣列一樣,但它的size可以動態改變。

  vector的元素在記憶體中連續排列,這一點跟陣列一樣。這意味著我們元素的索引將非常快,而且也可以通過指標的偏移來獲取vector中的元素。

  但連續排列也帶來了弊端,當我們向vector中間插入一個數據時,整個vector的size變大,在記憶體中就需要重新分配空間,常規的做法是直接申請一個新的array,並將所有元素拷貝過去;但這麼做的話,無疑太浪費時間,因此vector採用的做法是:vector會分配額外的空間,以適應size的動態增長。因此,包含同樣數量元素的vector和陣列相比,佔用的空間會更大。而且在vector最後增加或者刪除一個元素,消耗的時間是一個常數值,與vector的size無關。

  與其他容器(deques、lists、forward_lists)相比,vector在獲取元素和對最後一個元素的操作效率上更高;但對於中間元素的操作,效能則相對較差。

vector的使用

標頭檔案

#include

建立vector物件

std::vector<int>vec1;//空的vector,資料型別為int
std::vector<int>vec2(4);//4個值為0的vector
std::vector<int>vec3(4,10);//4個值為10的vector[10101010]
std::vector<int>vec4(vec3.begin(),vec3.end());//[10101010]
std::vector<int>vec5(vec3);//[10101010]
std::vector<int>vec6={10,20,30,40};//[10203040]

屬性及操作

Iterators

NameDescription
begin返回指向迭代器第一個元素的指標
end返回指向迭代器最後一個元素的指標
rbegin返回迭代器逆序第一個元素的指標
rend返回迭代器逆序最後一個元素的指標
cbegin返回常量迭代器的第一個元素的指標
cend返回常量迭代器的最第一個元素的指標
crbegin返回常量迭代器逆序的第一個元素的指標
crend返回常量迭代器逆序的最後一個元素的指標

Capacity

NameDescription
size返回當前vector使用資料量的大小
max_size返回vector最大可用的資料量
resize調整vector中的元素個數
capacity返回vector中總共可以容納的元素個數
empty測試vector是否是空的
reserve控制vector的預留空間
shrink_to_fit減少capacity到size的大小

Element access

NameDescription
operator[]在[]中可以做運算
atvector.at(i)相當於vector[i]
front返回第一個元素的值
back返回最後一個元素的值
data返回指向vector記憶體資料的指標

Modifiers

NameDescription
assign指定vector內容
push_back在容器的最後一個位置插入元素x
pop_back刪除最後一個元素
insert插入元素
erase擦除元素
swap交換兩個容器的內容
clear將容器裡的內容清空,size值為0,但是儲存空間沒有改變
emplace插入元素(與insert有區別)
emplace_back在容器的最後一個位置插入元素x(與push_back有區別)

Allocator

NameDescription
get_allocator返回vector的記憶體分配器

具體使用方法

Iterators

  Iterators使用方式比較簡單,下面的程式也很直觀的展現了它們的用法。其中it3it4for中使用auto來定義,使用更加方便。

#include
#include

usingnamespacestd;

intmain(){
vector<int>vec0;

for(inti=0;i10;++i){
vec0.push_back(i);//[0,1,2,3,4,5,6,7,8,9]
}

vector<int>::iteratorit1;
for(it1=vec0.begin();it1!=vec0.end();++it1){
cout<''<endl;//[0,1,2,3,4,5,6,7,8,9]
}

vector<int>::reverse_iteratorit2;
for(it2=vec0.rbegin();it2!=vec0.rend();++it2){
cout<''<endl;//[9,8,7,6,5,4,3,2,1,0]
}

for(autoit3=vec0.cbegin();it3!=vec0.end();++it3){
cout<''<endl;//[0,1,2,3,4,5,6,7,8,9]
}

for(autoit4=vec0.crbegin();it4!=vec0.crend();++it4){
cout<''<endl;//[9,8,7,6,5,4,3,2,1,0]
}

return0;
}

  如果是vec0.begin()+1,則表示從第二個元素開始。

Capacity

  Capacity中的幾個函式,從描述上看有點模糊,下面我們具體解釋一下。

  • size返回的是當前vector中有多少元素;

  • max_size返回的是最大可用的資料量,這跟實際的硬體有關,但也並不是所有的記憶體空間都可用,比如下面程式中的執行的記憶體大小為32GByte,但返回的結果是4GByte;

  • capacity是當前vector分配的可以容納的元素個數,下面的程式碼中,vec0可以容納13個元素,但僅包含了size(即10)個元素,還有3個元素可以放進去,當再放入超過3個元素後,vec0就會被重新分配空間;所以,capacity始終大於等於size

  • resize把容器改為容納n個元素。呼叫resize之後,size將會變為n;其中n又分了三種情況,當n

    capacity時,size和capacity同時變為n,新增加的元素都是0;
  • empty比較簡單,當vector為空時,返回1,不為空返回0;

  • shrink_to_fit,去掉預留的空間,capacity與size保持一致

#include
#include

usingnamespacestd;

intmain(){
vector<int>vec0;
cout<"vec0emptystatus:"<endl;//1

for(inti=0;i10;++i){
vec0.push_back(i);//[0,1,2,3,4,5,6,7,8,9]
}

cout<"vec0emptystatus:"<endl;//0

//---------------Capacity--------------------------
cout<"vec0size:"<endl;//10
cout<"vec0maxsize:"<endl;//1073741823=4GByte
cout<"vec0capacity:"<endl;//13
vec0.resize(20);
cout<"newsize:"<"newcapacity:"<endl;//2020
vec0.resize(5);
cout<"newsize:"<"newcapacity:"<endl;//520
vec0.shrink_to_fit();
cout<"newsize:"<"newcapacity:"<endl;//55

return0;
}
  • reserve用來指定vector的預留空間,在上面的程式碼中,沒有resize前capacity是值為13,但我們可以提前指定vector的容量。

#include
#include

usingnamespacestd;

intmain(){
//---------------reserve-----------------------------
std::vector<int>vec0;
intsz;
sz=vec0.capacity();
std::cout<"makingvec0grow:\n";
for(inti=0;i100;++i){
vec0.push_back(i);
if(sz!=vec0.capacity()){
sz=vec0.capacity();
std::cout<"capacitychanged:"<'\n';
}
}

std::vector<int>vec1;
sz=vec1.capacity();
vec1.reserve(100);//thisistheonlydifferencewithvec0above
std::cout<"makingvec1grow:\n";
for(inti=0;i100;++i){
vec1.push_back(i);
if(sz!=vec1.capacity()){
sz=vec1.capacity();
std::cout<"capacitychanged:"<'\n';
}
}
return0;
}

列印結果為:

makingvec0grow:
capacitychanged:1
capacitychanged:2
capacitychanged:3
capacitychanged:4
capacitychanged:6
capacitychanged:9
capacitychanged:13
capacitychanged:19
capacitychanged:28
capacitychanged:42
capacitychanged:63
capacitychanged:94
capacitychanged:141
makingvec1grow:
capacitychanged:100

Element access

  vector元素獲取的使用方法也比較簡單,下面的程式碼可以很好的展示:

vector<int>vec0;
for(inti=0;i10;++i){
vec0.push_back(i);//[0,1,2,3,4,5,6,7,8,9]
}

for(unsignedinti=0;icout<endl;//[0,1,2,3,4,5,6,7,8,9]
}

cout<"frontelement:"<endl;//0
cout<"backelement:"<endl;//9

vector<int>vec1(5);//[0,0,0,0,0]
int*p=vec1.data();//vec1mustnotbeempty
for(unsignedinti=0;i*p=i;
++p;
}
for(unsignedinti=0;icout<endl;//[0,1,2,3,4]
}

Modifiers

  assign主要有三種用法,如下面的demo所示:

vector<int>vec1;
vector<int>vec2;
vector<int>vec3;

vec1.assign(5,10);//[10,10,10,10,10]

vector<int>::iteratorit;
it=vec1.begin()+1;

vec2.assign(it,vec1.end()-1);//[10,10,10]

intarr[]={10,20,30,40};
vec3.assign(arr,arr+4);//[10,20,30,40]

  push_backpop_back用法比較簡單

vec0.push_back(55);
cout<"Lastelement:"<"size:"<endl;//5511
vec0.pop_back();
cout<"Lastelement:"<"size:"<endl;//910

  在vector中,有插入元素功能的函式有四個:push_backinsertemplaceemplace_back,其中push_back上面講了,emplace_back是在C++11中引入的,用法跟push_back完全一樣,都是在vector的最後插入一個元素。

vec3.emplace_back(100);

那為什麼要引入一個用法完全一樣的函式?因為它們的底層實現方式不同,push_back向容器尾部新增元素時,然後再將這個元素拷貝或者移動到容器中(如果是拷貝的話,事後會自行銷燬先前建立的這個元素);而 emplace_back 在實現時,則是直接在容器尾部建立這個元素,省去了拷貝或移動元素的過程。

  insertemplace(C++11中引入)都可以向vector中間插入元素,但insert可以插入多個元素,emplace一次只能插入一個元素。

  insert有三種用法:

  1. 在指定位置loc前插入值為val的元素,返回指向這個元素的迭代器,

  2. 在指定位置loc前插入num個值為val的元素

  3. 在指定位置loc前插入區間[start, end)的所有元素

//method1
vector<int>vec1;
intarr[]={1,2,3,4,5};
vec1.insert(vec1.begin(),arr,arr+5);//[1,2,3,4,5]

//method2
vector<int>vec2(vec1);
vector<int>::iteratorit=vec1.begin()+2;
vec1.insert(it,3,20);//[1,2,20,20,20,3,4,5]

//method3
vector<int>vec3(3,40);
vector<int>::iteratorit2=vec2.begin();
vec2.insert(it2,vec3.begin(),vec3.end());//[40,40,40,1,2,3,4,5]

  emplace的使用方式為:

iteratoremplace(const_iteratorpos,args...);
vector<int>vec0{1,2,3};
vec0.emplace(vec0.begin()+2,10);//[1,2,10,3]

  若都是插入一個元素的情況下,該使用哪個函式呢?當然是C++11中新引入的emplaceemplace在插入元素時,在指定位置直接構造元素,而insert是生成元素,再將其賦值或移動到容器中。

  vector中有三種可以刪除元素的操作,第一種就是我們上面講到的pop_back,刪除最後一個元素,無返回值;第二種是clear,將容器清空,size變為0,無返回值;第三種是erase,通過迭代器來刪除元素,可以刪除一個元素,也可以刪除某個範圍內的元素,返回下一個位置的迭代器。

vector<int>vec0{1,2,3,4,5,6,7,8,9,10};
//for(inti=0;i4;++i){
//vec0.pop_back();
//}
vec0.erase(vec0.begin()+3);//[1,2,3,5,6,7,8,9,10]
vec0.erase(vec0.begin(),vec0.begin()+5);//[7,8,9,10]
//vec0.clear();

  swap的用法也比較簡單,就是交換兩個vector的內容

vector<int>vec1{1,2,3,4,5};
vector<int>vec2{10,20,30};
vec1.swap(vec2);

Allocator

  get_allocator用的不是特別多,我們把使用方法講一下。

vector<int>myvector;
int*p;
unsignedinti;

//使用Allocator為陣列分配5個元素的空間
p=myvector.get_allocator().allocate(5);


for(i=0;i<5;i++)myvector.get_allocator().construct(&p[i],i);

std::cout<"Theallocatedarraycontains:";
for(i=0;i<5;i++)std::cout<''<//[0,1,2,3,4]


for(i=0;i<5;i++)myvector.get_allocator().destroy(&p[i]);
myvector.get_allocator().deallocate(p,5);

二維陣列

  上面我們講的,都相當於是一維陣列,vector還支援二維陣列,但這種二維陣列是通過巢狀的方式來實現,並不像Python或者Matlab的矩陣那麼直觀。

vector<vector<int>>arr(3);
for(inti=0;i3;++i){
arr[i].resize(3);//3x3array
}
for(inti=0;i3;++i)
for(intk=0;k3;++k)
arr[i][k]=i*k;//賦值
arr.resize(4);//二維陣列包含4個變數
arr[2].resize(5);//第3個變數包含5個變數

往期文章:

  • SystemVerilog教程之資料型別1

  • Vivado中模組封裝成edif和dcp

  • 自動駕駛入門之視覺定位座標轉換

  • 什麼是噪聲溫度?-174dBm/Hz又是什麼?

  • FPGA 中的有符號數乘法

  • 為什麼推薦使用XPM?

  • RAM IP Core中 Write First Read First和No Change的區別

  • Vivado除錯小結:ILA debug中的資料也許並不可信

  • FPGA復位的正確開啟方式

  • 如何使用Git進行Vivado工程的管理

  • 大家一致避免使用的鎖存器為什麼依然存在於FPGA中?我們對鎖存器有什麼誤解?

  • 影響FPGA時序的進位鏈(Carry Chain), 你用對了麼??

  • Virtex7 Microblaze下DDR3測試

  • Matlab高效程式設計技巧

  • 生成Verilog HDL例化模板

  • DCM/DLL/PLL/MMCM區別

FPGA時序約束教程:

  1. FPGA時序約束理論篇之建立保持時間

  2. FPGA時序約束理論篇之時序路徑與時序模型

3.FPGA時序約束理論篇之IO約束

4.FPGA時序約束理論篇之時鐘週期約束

5.FPGA時序約束理論篇之兩種時序例外

6.FPGA時序約束理論篇之xdc約束優先順序

7.FPGA時序約束實戰篇之梳理時鐘樹

8.FPGA時序約束實戰篇之主時鐘約束

9.FPGA時序約束實戰篇之衍生時鐘約束

10.FPGA時序約束實戰篇之延遲約束

11.FPGA時序約束實戰篇之偽路徑約束

12.FPGA時序約束實戰篇之多週期路徑約束

13.Vivado時序約束輔助工具

14.FPGA時序約束之Tcl命令的物件及屬性

歡迎關注微信公眾號:

9ce00ebe-c217-eb11-8da9-e4434bdf6706.jpeg

加FPGA技術交流群的朋友,請加微信:xhclsys2