最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

動態(tài)數(shù)組和C++ std::vector詳解

2023-07-11 10:23 作者:艱默  | 我要投稿


1. std::vector

std::vector是C++的默認(rèn)動態(tài)數(shù)組,其與array最大的區(qū)別在于vector的數(shù)組是動態(tài)的,即其大小可以在運行時更改。std::vector是封裝動態(tài)數(shù)組的順序容器,且該容器中元素的存取是連續(xù)的。

vector的存儲是自動管理,不需要人為操作自動實現(xiàn)按需擴(kuò)張收縮。但實現(xiàn)自動管理的代價就是:vector通常占用多于靜態(tài)數(shù)組的空間,因為其需要更多的內(nèi)存以管理將來的增長。vector在分配內(nèi)存的時候是先分配一定數(shù)量的內(nèi)存,然后在內(nèi)存耗盡時再重新申請分配。

2. vector的用法

2.1 vector的定義和聲明

std::vector在頭文件<vector>中定義,其聲明如下:

template<
????class?T,
????class?Allocator?=?std:
:allocator<T>
>?class?vector;

namespace?pmr?{
????template<?class?T?>
????using?vector?=?std:
:vector<T,?std::pmr::polymorphic_allocator<T>>;?//C++17?起
}??????????????????????????????????????????????????????????????????????

其中,參數(shù)T為容器要存儲的元素類型,對于T需要滿足:

  • 可復(fù)制賦值和可復(fù)制構(gòu)造(C++11前)。

  • 要求元素類型是完整類型并滿足可擦除,即元素類型的對象能以給定的分配器(Allocator)銷毀(C++11 起,C++17 前)。

  • 要求元素類型是完整類型并滿足可擦除,但許多成員函數(shù)附帶了更嚴(yán)格的要求。(C++17 起)。

Allocator為用于獲取/釋放內(nèi)存及構(gòu)造/析構(gòu)內(nèi)存中元素的分配器。

2.2 成員函數(shù)

2.2.1 基本函數(shù)

operator=

operator=函數(shù)主要適用于賦值給容器,其函數(shù)聲明如下:

/*1.?復(fù)制賦值運算符。以?other?的副本替換內(nèi)容。*/
vector&?operator=(?const?vector&?other?);?//C++20?前
constexpr?vector&?operator=(?const?vector&?other?);?//C++20?起

/*2.?移動賦值運算符。用移動語義以?other?的內(nèi)容替換內(nèi)容(即從?other?移動?other?中的數(shù)據(jù)到此容器中)。
?????之后?other?在合法但未指定的狀態(tài)。*/

vector&?operator=(?vector&&?other?);?//C++11?起,?C++17?前
vector&?operator=(?vector&&?other?)?noexcept();?//C++17?起,?C++20?前
constexpr?vector&?operator=(?vector&&?other?)?noexcept();?//C++20?起

/*3.?以?initializer_list?ilist?所標(biāo)識者替換內(nèi)容。*/
vector&?operator=(?std::initializer_list<T>?ilist?);?//C++11?起,?C++20?前
constexpr?vector&?operator=(?std::initializer_list<T>?ilist?);?//C++20?起

復(fù)雜度:

  • 1的復(fù)雜度與 *thisother 的大小成線性。

  • 2的復(fù)雜度與 *this 的大小成線性,除非分配器不比較相等且不傳播,該情況下與 *thisother 的大小成線性。

  • 3的復(fù)雜度與 *thisilist 的大小成線性。

具體的示例如下:

std::vector<int>?nums1?{3,?1,?4,?6,?5,?9};
std::vector<int>?nums2;
std::vector<int>?nums3;

//?從?nums1?復(fù)制賦值數(shù)據(jù)到?nums2
nums2?=?nums1;
//此時nums2?=?{3,?1,?4,?6,?5,?9}

//?從?nums1?移動賦值數(shù)據(jù)到?nums3,
//?修改?nums1?和?nums3
nums3?=?std::move(nums1);
//此時?nums1?=?{},?nums3?=?{3,?1,?4,?6,?5,?9}


//?initializer_list?的復(fù)制賦值復(fù)制數(shù)據(jù)給?nums3
nums3?=?{1,?2,?3};
//此時nums3?=?{1,?2,?3}

assign

assign函數(shù)的主要作用是將值賦給容器。其函數(shù)聲明如下:

/*1.?以?count?份?value?的副本替換內(nèi)容。*/
void?assign(?size_type?count,?const?T&?value?);?//C++20?前
constexpr?void?assign(?size_type?count,?const?T&?value?);?//C++20?起

/*2.?以范圍?[first,?last)?中元素的副本替換內(nèi)容。其中有任何一個迭代器是指向?*this?中的迭代器時行為未定義。*/
template<?class?InputIt?>
void?assign(?InputIt?first,?InputIt?last?)
;?//C++20?前
template<?class?InputIt?>
constexpr?void?assign(?InputIt?first,?InputIt?last?)
;?//C++20?起

/*3.?以來自?initializer_list?ilist?的元素替換內(nèi)容。*/
void?assign(?std::initializer_list<T>?ilist?);?//C++11?起,C++20?前
constexpr?void?assign(?std::initializer_list<T>?ilist?);?//C++20?起

復(fù)雜度:

  • 1的復(fù)雜度與count 呈線性。

  • 2的負(fù)載度與 firstlast 間的距離呈線性。

  • 3的復(fù)雜度與與 ilist.size() 呈線性。

其具體用法如下:

std::vector<char>?c;

c.assign(5,?'a');//此時c?=?{'a',?'a',?'a',?'a',?'a'}

const?std::string?str(6,?'b');
c.assign(str.begin(),?str.end());//此時c?=?{'b',?'b',?'b',?'b',?'b',?'b'}

c.assign({'C',?'+',?'+',?'1',?'1'});//此時c?=?{'C',?'+',?'+',?'1',?'1'}

get_allocator

get_allocator函數(shù)的主要作用是返回相關(guān)的分配器。其函數(shù)聲明如下:

allocator_type?get_allocator()?const;?//C++11?前
allocator_type?get_allocator()?const?noexcept;?//C++11?起,?C++20?前
constexpr?allocator_type?get_allocator()?const?noexcept;?//C++20?起

其返回值為與容器關(guān)聯(lián)的分配器。

2.2.2 元素訪問

at

at用于訪問指定的元素,同時進(jìn)行越界檢查,該函數(shù)返回位于指定位置pos的元素的引用,如果pos不在容器的范圍內(nèi),則拋出std::out_of_range異常。其函數(shù)聲明如下:

reference?at(?size_type?pos?);?//C++20?前
constexpr?reference?at(?size_type?pos?);?//C++20?起
const_reference?at(?size_type?pos?)?const;?//C++20?前
constexpr?const_reference?at(?size_type?pos?)?const;?//C++20?起

其具體用法如下:

std::vector<int>?data?=?{1,?2,?3};

std::cout<<data.at(1)<<std::endl;?//2
data.at(1)=8;?//此時data={1,?8,?3}

operator[]

operator[]與at功能相同,即用來訪問指定的元素,但其與at不同的是:operator[]不進(jìn)行邊界的檢查。其函數(shù)聲明如下所示:

reference?operator[](?size_type?pos?);?//C++20?前
constexpr?reference?operator[](?size_type?pos?);?//C++20?起
const_reference?operator[](?size_type?pos?)?const;?//C++20?前
constexpr?const_reference?operator[](?size_type?pos?)?const;?//C++20?起

front

front用于訪問容器的第一個元素,其返回值為容器首元素的引用,其函數(shù)原型如下:

reference?front();?//C++20?前
constexpr?reference?front();?//C++20?起
const_reference?front()?const;?//C++20?前
constexpr?const_reference?front()?const;?//C++20?起

:在空容器上對 front 的調(diào)用是未定義的。

back

back主要功能是用來訪問容器最后一個元素,其返回值為容器最后一個元素的引用,其函數(shù)原型如下所示:

reference?back();?//C++20?前
constexpr?reference?back();?//C++20?起
const_reference?back()?const;?//C++20?前
constexpr?const_reference?back()?const;?//C++20?起

:在空容器上對 back 的調(diào)用是未定義的。

data

data函數(shù)主要是用來返回容器底層的數(shù)組,其函數(shù)原型如下:

T*?data();?//C++11?前
T*?data()?noexcept;?//C++11?起,?C++20?前
constexpr?T*?data()?noexcept;?//C++20?起
const?T*?data()?const;?//C++11?前
const?T*?data()?const?noexcept;?//C++11?起,?C++20?前
constexpr?const?T*?data()?const?noexcept;?//C++20?起

data函數(shù)返回指向作為元素存儲工作的底層數(shù)組的指針。返回的指針使得范圍 [data(), data() + size()) 始終是合法范圍,即使容器為空(此時 data() 不可解引用)。

:如果 size() 是 0,那么 data() 有可能會也有可能不會返回空指針。

2.2.3 迭代器

begin、end和cbegin、cend

begin和cbegin返回指向vector首元素的迭代器,end和cend返回指向vector末元素后一元素的迭代器。其函數(shù)聲明如下:

iterator?begin();?//C++11?前
iterator?begin()?noexcept;?//C++11?起,C++20?前
constexpr?iterator?begin()?noexcept;?//C++20?起
const_iterator?begin()?const;?//C++11?前
const_iterator?begin()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_iterator?begin()?const?noexcept;?//C++20?起
const_iterator?cbegin()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_iterator?cbegin()?const?noexcept;?//C++20?起


iterator?end();?//C++11?前
iterator?end()?noexcept;?//C++11?起,C++20?前
constexpr?iterator?end()?noexcept;?//C++20?起
const_iterator?end()?const;?//C++11?前
const_iterator?end()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_iterator?end()?const?noexcept;?//C++20?起
const_iterator?cend()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_iterator?cend()?const?noexcept;?//C++20?起

如果vector為空,則返回的迭代器將等于end或cend。end和cend指向vector末元素后一元素的迭代器,該元素的表現(xiàn)為占位符,試圖訪問它將導(dǎo)致未定義行為。

rbegin、rend和crbegin、crend

rbegin和crbegin返回指向vector首元素的逆向迭代器。它對應(yīng)非逆向vector的末元素,若vector為空,則返回的迭代器等于rend或crend。rend和crend返回指向逆向vector末元素后一元素的逆向迭代器,它對應(yīng)非逆向vector首元素的前一元素,此元素表現(xiàn)為占位符,試圖訪問它導(dǎo)致未定義行為。它們的聲明如下:

reverse_iterator?rbegin();?//C++11?前
reverse_iterator?rbegin()?noexcept;?//C++11?起,C++20?前
constexpr?reverse_iterator?rbegin()?noexcept;?//C++20?起
const_reverse_iterator?rbegin()?const;?//C++11?前
const_reverse_iterator?rbegin()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_reverse_iterator?rbegin()?const?noexcept;?//C++20?起
const_reverse_iterator?crbegin()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_reverse_iterator?crbegin()?const?noexcept;?//C++20?起

reverse_iterator?rend();?//C++11?前
reverse_iterator?rend()?noexcept;?//C++11?起,C++20?前
constexpr?reverse_iterator?rend()?noexcept;?//C++20?起
const_reverse_iterator?rend()?const;?//C++11?前
const_reverse_iterator?rend()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_reverse_iterator?rend()?const?noexcept;?//C++20?起
const_reverse_iterator?crend()?const?noexcept;?//C++11?起,C++20?前
constexpr?const_reverse_iterator?crend()?const?noexcept;?//C++20?起

2.2.4 容量

empty

empty用來檢查容器是否為空,若為空則返回true,否則為false。其函數(shù)聲明如下:

bool?empty()?const;?//C++11?前
bool?empty()?const?noexcept;?//C++11?起,?C++20?前
[[nodiscard]]?bool?empty()?const?noexcept;?//C++20?起

其底層實現(xiàn)就是檢查容器是否無元素,即判斷是否begin() == end()。

size

size函數(shù)返回容器中元素數(shù)量,即std::distance(begin(), end()) 。其函數(shù)聲明如下:

size_type?size()?const;?//C++11?前
size_type?size()?const?noexcept;?//C++11?起,C++20?前
constexpr?size_type?size()?const?noexcept;?//C++20?起

max_size

max_size函數(shù)返回根據(jù)系統(tǒng)或庫實現(xiàn)限制的容器可保有的元素最大數(shù)量,即對于最大容器std::distance(begin(), end())。其函數(shù)聲明為:

size_type?max_size()?const;?//C++11?前
size_type?max_size()?const?noexcept;?//C++11?起

:此值通常反映容器大小上的理論極限,至多為 std::numeric_limits<difference_type>::max() 。運行時,可用 RAM 總量可能會限制容器大小到小于 max_size() 的值。

capacity

capacity函數(shù)的主要作用是返回當(dāng)前存儲空間能夠容納的元素數(shù)(即當(dāng)前分配存儲的容量)。其函數(shù)原型如下:

size_type?capacity()?const;?//C++11?前
size_type?capacity()?const?noexcept;?//C++11?起,?C++20?前
constexpr?size_type?capacity()?const?noexcept;?//C++20?起

reserve

reserve函數(shù)是用來為vector預(yù)留存儲空間,其函數(shù)聲明如下:

//new_cap:?vector?的新容量
void?reserve(?size_type?new_cap?);?//C++20?前
constexpr?void?reserve(?size_type?new_cap?);?//C++20?起

該函數(shù)主要用來增加vector的容量(即 vector 在不重新分配存儲的情況下能最多能持有的元素的數(shù)量)到大于或者等于new_cap的值。如果new_cap大于當(dāng)前vector的capacity(),那么就會重新分配新的存儲,否則該方法不做任何事情。

  • reserve() 不會更改 vector 的大小。

  • 如果 new_cap 大于 capacity(),那么所有迭代器,包含 end()迭代器和所有到元素的引用都會失效。否則,沒有迭代器或引用會失效。

  • 在調(diào)用 reserve() 后,插入只會在它將導(dǎo)致 vector 的大小大于capacity()的值時觸發(fā)重新分配。

  • new_cap > max_size() 時拋出std::length_error。

  • 不能用 reserve() 減少容器容量。為該目的提供的是 shrink_to_fit()。 (文章后面有詳細(xì)的介紹)

正確的使用reserve能夠避免減少不必要的分配,例如在向vector添加元素之前提前知道元素的大致數(shù)量,使用reserve,可以提前合理分配好存儲空間,避免在vector增長階段不必要的內(nèi)存分配和復(fù)制,進(jìn)而提高效率和存儲空間的利用率。

shrink_to_fit

shrink_to_fit函數(shù)主要是用來請求移除未使用的容量。其函數(shù)原型如下:

void?shrink_to_fit();

它是減少 capacity() size()非強制性請求。請求是否達(dá)成依賴于實現(xiàn)。如果發(fā)生重分配,那么所有迭代器,包含 end()迭代器,和所有到元素的引用都會失效。如果沒有發(fā)生重分配,那么沒有迭代器或引用會失效。

具體的示例如下:

std::vector<int>?vec?=?{1,?2,?3};
vec.reserve(100);
std::cout?<<?"vec的capacity?:?"?<<?vec.capacity()?<<?std::endl;?//vec的capacity?:?100
vec.shrink_to_fit();
std::cout?<<?"vec的capacity?:?"?<<?vec.capacity()?<<?std::endl;?//vec的capacity?:?3

2.2.5 修改器

clear

clear函數(shù)主要用來擦除所有元素,使用clear()后,再次調(diào)用size(),size函數(shù)返回0。clear函數(shù)的聲明如下:

void?clear();?//C++11?前
void?clear()?noexcept;?//C++11?起,?C++20?前
constexpr?void?clear()?noexcept;?//C++20?起

:clear不會影響vector的capacity()的大小。

insert

insert函數(shù)主要用于插入元素到容器的指定位置,其函數(shù)原型如下所示:

//在?pos?前插入?value
//返回值:指向被插入?value?的迭代器。
iterator?insert(?const_iterator?pos,?const?T&?value?);?//C++20?前
constexpr?iterator?insert(?const_iterator?pos,?const?T&?value?);?//C++20?起

//在?pos?前插入?value
//返回值:指向被插入?value?的迭代器。
iterator?insert(?const_iterator?pos,?T&&?value?);?//C++11?起,C++20?前
constexpr?iterator?insert(?const_iterator?pos,?T&&?value?);?//C++20?起

//在?pos?前插入?value?的?count?個副本。
//返回值:指向首個被插入元素的迭代器,或者在?count?==?0?時返回?pos。
iterator?insert(?const_iterator?pos,?size_type?count,?const?T&?value?);?//C++20?前
constexpr?iterator
????insert(?const_iterator?pos,?size_type?count,?const?T&?value?)
;?//C++20?起

//在?pos?前插入來自范圍?[first,?last)?的元素。
//返回值:指向首個被插入元素的迭代器,或者在?first?==?last?時返回?pos。
template<?class?InputIt?>
iterator?insert(?const_iterator?pos,?InputIt?first,?InputIt?last?)
;?//C++20?前
template<?class?InputIt?>
constexpr?iterator?insert(?const_iterator?pos,?InputIt?first,?InputIt?last?)
;?//C++20?起

//在?pos?前插入來自?initializer_list?ilist?的元素。
//返回值:指向首個被插入元素的迭代器,或者在?ilist?為空時返回?pos。
iterator?insert(?const_iterator?pos,?std::initializer_list<T>?ilist?);?//C++11?起,C++20?前
constexpr?iterator?insert(?const_iterator?pos,
???????????????????????????std::initializer_list<T>?ilist?)
;?//C++20?起

具體用法示例如下:

std::vector<int>?c1(3,?100);?//初始化c1,此時c1?=?{100,?100,?100}

auto?it?=?c1.begin();
it?=?c1.insert(it,?200);?//在it前插入元素200
//c1?=?{200,100,?100,?100}

c1.insert(it,?2,?300);?//在it前插入兩個元素值都為300
//c1?=?{300,300,200,100,?100,?100}

//?it?已經(jīng)失效,提供新迭代器
it?=?c1.begin();

std::vector<int>?c2(2,?400);?//c2?=?{400,?400}
c1.insert(std::next(it,?2),?c2.begin(),?c2.end());?//在it后兩個元素(即200)的前面插入c2
//c1?=?{300,300,400,400,200,100,?100,?100}

int?arr[]?=?{501,?502,?503};
c1.insert(c1.begin(),?arr,?arr?+?std::size(arr));
//c1?=?{501,502,503,300,300,400,400,200,100,?100,?100}

c1.insert(c1.end(),?{601,?602,?603});
//c1?=?{501,502,503,300,300,400,400,200,100,?100,?100,601,602,603}

emplace

emplace函數(shù)的聲明如下:

/*----------------------------------
??pos:將構(gòu)造新元素到其前的迭代器
??args:轉(zhuǎn)發(fā)給元素構(gòu)造函數(shù)的參數(shù)
??返回值iterator:指向被安置的元素的迭代器
------------------------------------*/

template<?class...?Args?>
iterator?emplace(?const_iterator?pos,?Args&&...?args?)
;?//C++11?起,?C++20?前

template<?class...?Args?>
constexpr?iterator?emplace(?const_iterator?pos,?Args&&...?args?)
;?//C++20?起

其主要作用就是原位構(gòu)造元素并將其在pos前插入到容器中。

earse

earse的函數(shù)主要功能是擦除元素,其聲明如下:

//移除位于pos的元素
//返回值:最后移除元素之后的迭代器。如果pos指代末元素,則返回end()迭代器
iterator?erase(?iterator?pos?);?//C++11?前
iterator?erase(?const_iterator?pos?);?//C++11?起,C++20?前
constexpr?iterator?erase(?const_iterator?pos?);?//C++20?起

//移除范圍[first,?last)中的元素。
/*返回值:最后移除元素之后的迭代器。
?????????如果在移除前l(fā)ast?==?end(),那么最終返回end()迭代器
?????????如果范圍[first,?last)?為空,那么返回?last。*/

iterator?erase(?iterator?first,?iterator?last?);?//C++11?前
iterator?erase(?const_iterator?first,?const_iterator?last?);?//C++11?起,C++20?前
constexpr?iterator?erase(?const_iterator?first,?const_iterator?last?);?//C++20?起

具體的用法如下所示:

std::vector<int>?c{0,?1,?2,?3,?4,?5,?6,?7,?8,?9};

c.erase(c.begin());
//c?=?{1,?2,?3,?4,?5,?6,?7,?8,?9}

c.erase(c.begin()?+?2,?c.begin()?+?5);
//c?=?{1,?2,?6,?7,?8,?9}

//?移除所有偶數(shù)
for?(std::vector<int>::iterator?it?=?c.begin();?it?!=?c.end();)
{
??if?(*it?%?2?==?0)
????it?=?c.erase(it);
??else
????++it;
}
//c?=?{1,?7,?9}

push_back

push_back函數(shù)的主要作用是將元素添加到容器末尾,其聲明如下:

//后附給定元素?value?到容器尾。初始化新元素為?value?的副本。
void?push_back(?const?T&?value?);?//C++20?前
constexpr?void?push_back(?const?T&?value?);?//C++20?起

//后附給定元素?value?到容器尾。移動?value?進(jìn)新元素。
void?push_back(?T&&?value?);?//C++11?起,C++20?前
constexpr?void?push_back(?T&&?value?);?//C++20?起

:如果新的 size()大于 capacity(),那么所有迭代器和引用(包含 end() 迭代器)都會失效。否則只有 end() 迭代器會失效。

emplace_back

emplace_back函數(shù)與emplace類似,只不過是在容器末尾就地構(gòu)造元素,其函數(shù)聲明如下:

template<?class...?Args?>
void?emplace_back(?Args&&...?args?)
;?//C++11?起,?C++17?前

template<?class...?Args?>
reference?emplace_back(?Args&&...?args?)
;?//C++17?起,?C++20?前

template<?class...?Args?>
constexpr?reference?emplace_back(?Args&&...?args?)
;?//C++20?起

由于emplace_back是原地構(gòu)造元素,因此其插入效率要高于push_back。

:如果新的 size()大于 capacity(),那么所有迭代器和引用(包含 end() 迭代器)都會失效。否則只有 end() 迭代器會失效。

pop_back

pop_back函數(shù)的主要作用就是移除末元素,其函數(shù)聲明如下:

void?pop_back();?//C++20?前
constexpr?void?pop_back();?//C++20?起

如果在空容器上調(diào)用pop_back會導(dǎo)致未定義行為。

:使指向末元素的迭代器和引用,以及end()迭代器失效。

resize

resize函數(shù)的主要作用是改變?nèi)萜髦锌纱鎯υ氐膫€數(shù),通過該函數(shù)可以重新設(shè)置容器大小,其函數(shù)聲明如下:

/*
該函數(shù)重設(shè)容器的大小為count,在count==size()時不做任何操作。
如果當(dāng)前大小大于?count,那么減小容器到它的開頭?count?個元素。
如果當(dāng)前大小小于?count,那么后附額外的默認(rèn)插入的元素。
*/

void?resize(?size_type?count?);?//C++20?前
constexpr?void?resize(?size_type?count?);?//C++20?起

/*
該函數(shù)重設(shè)容器的大小為count,在count==size()時不做任何操作。
如果當(dāng)前大小大于?count,那么減小容器到它的開頭?count?個元素。
如果當(dāng)前大小小于?count,那么后附額外的?value?的副本
*/

void?resize(?size_type?count,?const?value_type&?value?);?//C++20?前
constexpr?void?resize(?size_type?count,?const?value_type&?value?);?//C++20?起

其具體用法示例如下:

std::vector<int>?c?=?{1,?2,?3};

c.resize(5);?//將其size增加大小到5
//c?=?{1,?2,?3,?0,?0}

c.resize(2);?//將其size減少大小到2
//c?=?{1,?2}

c.resize(6,?4);?//將其size增加大小到6,填充值為4";
//c?=?{1,?2,?4,?4,?4,4}

swap

swap函數(shù)的主要作用是交換兩個vector容器的內(nèi)容,不在單獨的元素上調(diào)用任何移動、復(fù)制或交換操作。所有迭代器和引用保持有效。end()迭代器會失效。其函數(shù)聲明如下:

void?swap(?vector&?other?);?//C++17?前
void?swap(?vector&?other?)?noexcept();?//C++17?起,?C++20?前
constexpr?void?swap(?vector&?other?)?noexcept();?//C++20?起

其用法示例如下圖所示:

std::vector<int>?a1{1,?2,?3},?a2{4,?5};

auto?it1?=?std::next(a1.begin());?//*it1?=?2?
auto?it2?=?std::next(a2.begin());?//*it2?=?5?

int&?ref1?=?a1.front();?//ref1?=?1
int&?ref2?=?a2.front();?//ref1?=?4

std::cout?<<*it1?<<?'?'?<<?*it2?<<?'?'?<<?ref1?<<?'?'?<<?ref2?<<?'\n';
//打印結(jié)果為2?5?1?4

a1.swap(a2);

//此時a1?=?{4,?5},a2?=?{1,?2,?3}
std::cout?<<*it1?<<?'?'?<<?*it2?<<?'?'?<<?ref1?<<?'?'?<<?ref2?<<?'\n';
//打印結(jié)果仍為2?5?1?4

/*注:
????交換后迭代器與引用保持與原來的元素關(guān)聯(lián),
????例如盡管?'a1'?中值為?2?的元素被移動到?'a2'?中,
????原來指向它的?it1?仍指向同一元素。*/

2.2 非成員函數(shù)

operator==,!=,<,<=,>,>=,<=>(std::vector)

C++提供operator==,!=,<,<=,>,>=,<=>(std::vector)非成員函數(shù)用來比較兩個vector的大小,相關(guān)函數(shù)及函數(shù)聲明如下:

//1.?==
//返回值:在?vector?內(nèi)容相等時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator==(?const?std:
:vector<T,?Alloc>&?lhs,
?????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前
template<?class?T,?class?Alloc?>
constexpr?bool?operator==(?const?std:
:vector<T,?Alloc>&?lhs,
???????????????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?起

//2.?!=
//返回值:在?vector?內(nèi)容不相等時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator!=(?const?std:
:vector<T,?Alloc>&?lhs,
?????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前

//3.?<
//返回值:在?lhs?的內(nèi)容按字典序小于?rhs?的內(nèi)容時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator<(?const?std::vector<T,?Alloc>&?lhs,
????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前

//4.?<=
//返回值:在?lhs?的內(nèi)容按字典序小于或等于?rhs?的內(nèi)容時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator<=(?const?std::vector<T,?Alloc>&?lhs,
?????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前

//5.?>
//返回值:在?lhs?的內(nèi)容按字典序大于?rhs?的內(nèi)容時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator>(?const?std::vector<T,?Alloc>&?lhs,
????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前

//6.?>=
//返回值:在?lhs?的內(nèi)容按字典序大于或等于?rhs?的內(nèi)容時返回?true,否則返回?false
template<?class?T,?class?Alloc?>
bool?operator>=(?const?std:
:vector<T,?Alloc>&?lhs,
?????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?前

//7.?<=>
//返回值:lhs?與?rhs?中的首對不等價元素的相對順序,如果有這種元素;否則是?lhs.size()?<=>?rhs.size()。
template<?class?T,?class?Alloc?>
constexpr??operator<=>(?const?std:
:vector<T,?Alloc>&?lhs,
???????????????????????????????????????const?std::vector<T,?Alloc>&?rhs?);?//C++20?起

  • 1,2中會檢查lhs和rhs的內(nèi)容是相等,即他們是否擁有相同數(shù)量的元素且lhs中每個元素與rhs的相同位置元素比較相等。同時函數(shù)中T 必須符合可相等比較 (EqualityComparable) 的要求

  • 3-6中按照字典比較lhs和rhs的內(nèi)容,其內(nèi)部等價于調(diào)用std::lexicographical_compare函數(shù)進(jìn)行比較。同時函數(shù)中T 必須符合[可小于比較 (LessThanComparable) 的要求。

  • 7中也是按字典序比較lhs和rhs的內(nèi)容。其內(nèi)部等價于調(diào)用std::lexicographical_compare_three_way 進(jìn)行比較。返回類型同合成三路比較的結(jié)果類型。其邏輯大致如下:

    lhs?<?rhs???std::weak_ordering::less?:
    rhs?<?lhs???std::weak_ordering::greater?:
    ????????????std::weak_ordering::equivalent
    //注:通常情況下less對應(yīng)的是-1,greater對應(yīng)1,equivalent對應(yīng)0

    lhs與rhs中的首對不等價元素的相對順序,如果有這種元素;否則是 lhs.size() <=> rhs.size()。

其具體的應(yīng)用示例如下所示:

std::vector<int>?alice{1,?2,?3};
std::vector<int>?bob{7,?8,?9,?10};
std::vector<int>?eve{1,?2,?3};

std::cout?<<?std::boolalpha;

//?比較不相等的容器
std::cout?<<?"alice?==?bob?returns?"?<<?(alice?==?bob)?<<?'\n';
std::cout?<<?"alice?!=?bob?returns?"?<<?(alice?!=?bob)?<<?'\n';
std::cout?<<?"alice?<??bob?returns?"?<<?(alice?<?bob)?<<?'\n';
std::cout?<<?"alice?<=?bob?returns?"?<<?(alice?<=?bob)?<<?'\n';
std::cout?<<?"alice?>??bob?returns?"?<<?(alice?>?bob)?<<?'\n';
std::cout?<<?"alice?>=?bob?returns?"?<<?(alice?>=?bob)?<<?'\n';

std::cout?<<?'\n';

//?比較相等的容器
std::cout?<<?"alice?==?eve?returns?"?<<?(alice?==?eve)?<<?'\n';
std::cout?<<?"alice?!=?eve?returns?"?<<?(alice?!=?eve)?<<?'\n';
std::cout?<<?"alice?<??eve?returns?"?<<?(alice?<?eve)?<<?'\n';
std::cout?<<?"alice?<=?eve?returns?"?<<?(alice?<=?eve)?<<?'\n';
std::cout?<<?"alice?>??eve?returns?"?<<?(alice?>?eve)?<<?'\n';
std::cout?<<?"alice?>=?eve?returns?"?<<?(alice?>=?eve)?<<?'\n';

輸出結(jié)果為

alice?==?bob?returns?false
alice?!=?bob?returns?true
alice?<??bob?returns?true
alice?<=?bob?returns?true
alice?>??bob?returns?false
alice?>=?bob?returns?false
?
alice?==?eve?returns?true
alice?!=?eve?returns?false
alice?<??eve?returns?false
alice?<=?eve?returns?true
alice?>??eve?returns?false
alice?>=?eve?returns?true

std::swap(std::vector)

std::swap(std::vector)函數(shù)是為std::vector特化std::swap 算法。其函數(shù)聲明如下:

template<?class?T,?class?Alloc?>
void?swap(?std::vector<T,?Alloc>&?lhs,
???????????std::vector<T,?Alloc>&?rhs?)
;?//C++11?起,?C++17?前

template<?class?T,?class?Alloc?>
void?swap(?std::vector<T,?Alloc>&?lhs,
???????????std::vector<T,?Alloc>&?rhs?)
?noexcept()
;//C++17?起,?C++20?前

template<?class?T,?class?Alloc?>
constexpr?void?swap(?std::vector<T,?Alloc>&?lhs,
?????????????????????std::vector<T,?Alloc>&?rhs?)
?noexcept()
;?//C++20?起

交換 lhsrhs 的內(nèi)容。調(diào)用lhs.swap(rhs)。其具體用法如下:

std::vector<int,?3>?a1{1,?2,?3},?a2{4,?5,?6};

auto?it1?=?a1.begin();?//*it1?=?1
auto?it2?=?a2.begin();?//*it2?=?4

int?&ref1?=?a1[1];?//?ref1?=?2
int?&ref2?=?a2[1];?//?ref1?=?5

std::cout?<<?*it1?<<?'?'?<<?*it2?<<?'?'?<<?ref1?<<?'?'?<<?ref2?<<?'\n';
//?打印結(jié)果為1?4?2?5

std::swap(a1,?a2);

//?此時a1?=?{4,?5,?6},a2?=?{1,?2,?3}
std::cout?<<?*it1?<<?'?'?<<?*it2?<<?'?'?<<?ref1?<<?'?'?<<?ref2?<<?'\n';
//?打印結(jié)果為4?1?5?2

std::erase, std::erase_if (std::vector)

std::erase, std::erase_if (std::vector)函數(shù)主要用來擦除所有滿足特定判別標(biāo)準(zhǔn)的元素。其函數(shù)聲明如下:

//從容器中擦除所有比較等于?value?的元素
template<?class?T,?class?Alloc,?class?U?>
constexpr?typename?std:
:vector<T,?Alloc>::size_type
????erase(std::vector<T,?Alloc>&?c,?const?U&?value)
;?//C++20?起

//從容器中擦除所有滿足?pred?的元素
template<?class?T,?class?Alloc,?class?Pred?>
constexpr?typename?std:
:vector<T,?Alloc>::size_type
????erase_if(std::vector<T,?Alloc>&?c,?Pred?pred)
;?//C++20?起

std::erase(std::vector)從容器中擦除所有比較等于 value 的元素,其返回值為被擦除的元素個數(shù),其等價于

auto?it?=?std::remove(c.begin(),?c.end(),?value);
auto?r?=?std::distance(it,?c.end());
c.erase(it,?c.end());
return?r;

std::erase_if (std::vector)從容器中擦除所有滿足 pred 的元素,其返回值為被擦除的元素個數(shù),其等價于

auto?it?=?std::remove_if(c.begin(),?c.end(),?pred);
auto?r?=?std::distance(it,?c.end());
c.erase(it,?c.end());
return?r;

示例:

std::vector<int>?c{1,?2,?3,?4,?6};
//?擦除c中的值等于3的元素
auto?erased1?=?std::erase(c,?3);?//?erased1?=?1
//?此時c?=?{1,?2,?4,?6}

//?擦除c中的偶數(shù)
auto?erased2?=?std::erase_if(c,?[](int?n)
?????????????????????????????{?return?n?%?2?==?0;?});?//?erased2?=?3
//?此時c?=?{1}

3. 總結(jié)

vector容器的優(yōu)勢和劣勢:

優(yōu)勢

  • 支持隨機訪問,訪問無開銷,時間恒定。

  • 線性遍歷/搜索。

  • 在容量滿足的情況下,末端插入元素效率高。

劣勢

  • 如果元素類型具有較高的復(fù)制/分配成本,則插入元素速度比較慢。

  • 如果隨之位置插入或擦除占程序的主導(dǎo)地位,程序會變慢。

vector容器在具體的應(yīng)用中需要注意一下幾點:

  1. 創(chuàng)建一個新vector

//?值列表初始化:?C++11
vector<int>?v?{0,?1,?2,?3};???//?v?=?{0,?1,?2,?3}

//?初始化一個長度為4,所有元素值都為2的vector
vector<int>?w?(4,?2)??//?w?=?{2,?2,?2,?2}
??
//?深拷貝,以v初始化vector對象b
vector<int>?b?
{v};?//?b?=?{0,?1,?2,?3}

  1. vector的size和capacity

  • size()代表vector中元素的數(shù)量

  • capacity()代表當(dāng)前vector中可以存儲元素數(shù)量的最大值。

    如果在向vector中添加元素之前提前知道元素(大致的)數(shù)量n,及時使用resrve(n),這樣可以避免在元素插入階段可能產(chǎn)生的不必要內(nèi)存分配和復(fù)制。

  1. 插入元素和擦除元素的效率

    在末尾插入元素的效率最快,但插入任意位置可能會很慢,因為中間可能涉及到元素的復(fù)制和移動。擦除元素同理。

  2. 使用shrink_to_fit()降低內(nèi)存

    從vector中擦除元素不會改變其容量,因此未存放的元素的位置對應(yīng)內(nèi)存不會被釋放,如果后續(xù)不需要再使用這些空閑的內(nèi)存,可以使用shrink_to_fit()對該內(nèi)存進(jìn)行釋放,提高內(nèi)存使用效率。

文章首發(fā)公眾號:iDoitnow如果喜歡話,可以關(guān)注一下

iDoitnow如果喜歡話,可以關(guān)注一下


動態(tài)數(shù)組和C++ std::vector詳解的評論 (共 條)

分享到微博請遵守國家法律
临江市| 仲巴县| 永修县| 南召县| 遂溪县| 于田县| 桐城市| 怀集县| 米易县| 关岭| 临城县| 铜山县| 肥城市| 枝江市| 东兴市| 封丘县| 南召县| 会泽县| 镇康县| 尼勒克县| 和平区| 唐山市| 循化| 新宁县| 潼南县| 深圳市| 淮阳县| 德安县| 抚州市| 长子县| 西盟| 兰州市| 福泉市| 合山市| 绍兴县| 肃南| 泾川县| 株洲市| 化德县| 华宁县| 启东市|