色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

動態數組和C++ std::vector詳解

冬至子 ? 來源:iDoitnow ? 作者:艱默 ? 2023-07-19 11:07 ? 次閱讀

1. std::vector

std::vectorC++的默認動態數組,其與array最大的區別在于vector的數組是動態的,即其大小可以在運行時更改。std::vector是封裝動態數組的順序容器,且該容器中元素的存取是連續的。

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

2. vector的用法

2.1 vector的定義和聲明

std::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 起
}

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

  • 可復制賦值和可復制構造(C++11前)。
  • 要求元素類型是完整類型并滿足可擦除,即元素類型的對象能以給定的分配器(Allocator)銷毀(C++11 起,C++17 前)。
  • 要求元素類型是完整類型并滿足可擦除,但許多成員函數附帶了更嚴格的要求。(C++17 起)。

Allocator為用于獲取/釋放內存及構造/析構內存中元素的分配器。

2.2 成員函數

2.2.1 基本函數

operator=

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

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

/*2. 移動賦值運算符。用移動語義以 other 的內容替換內容(即從 other 移動 other 中的數據到此容器中)。
     之后 other 在合法但未指定的狀態。*/
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 所標識者替換內容。*/
vector& operator=( std::initializer_list< T > ilist ); //C++11 起, C++20 前
constexpr vector& operator=( std::initializer_list< T > ilist ); //C++20 起

復雜度:

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

具體的示例如下:

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

// 從 nums1 復制賦值數據到 nums2
nums2 = nums1;
//此時nums2 = {3, 1, 4, 6, 5, 9}

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


// initializer_list 的復制賦值復制數據給 nums3
nums3 = {1, 2, 3};
//此時nums3 = {1, 2, 3}

assign

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

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

/*2. 以范圍 [first, last) 中元素的副本替換內容。其中有任何一個迭代器是指向 *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 的元素替換內容。*/
void assign( std::initializer_list< T > ilist ); //C++11 起,C++20 前
constexpr void assign( std::initializer_list< T > ilist ); //C++20 起

復雜度:

  • 1的復雜度與count呈線性。
  • 2的負載度與 firstlast間的距離呈線性。
  • 3的復雜度與與 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函數的主要作用是返回相關的分配器。其函數聲明如下:

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 起

其返回值為與容器關聯的分配器。

2.2.2 元素訪問

at

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

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<

operator[]

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

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用于訪問容器的第一個元素,其返回值為容器首元素的引用,其函數原型如下:

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

:在空容器上對 front 的調用是未定義的。

back

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

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

:在空容器上對 back 的調用是未定義的。

data

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

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

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

2.2.3 迭代器

begin、end和cbegin、cend

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

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末元素后一元素的迭代器,該元素的表現為占位符,試圖訪問它將導致未定義行為。

rbegin、rend和crbegin、crend

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

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。其函數聲明如下:

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

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

size

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

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函數返回根據系統或庫實現限制的容器可保有的元素最大數量,即對于最大容器std::distance(begin(), end())。其函數聲明為:

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

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

capacity

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

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函數是用來為vector預留存儲空間,其函數聲明如下:

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

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

  • reserve() 不會更改 vector 的大小。
  • 如果 new_cap 大于 capacity(),那么所有迭代器,包含 end()迭代器和所有到元素的引用都會失效。否則,沒有迭代器或引用會失效。
  • 在調用 reserve() 后,插入只會在它將導致 vector 的大小大于capacity()的值時觸發重新分配。
  • new_cap > max_size() 時拋出std::length_error
  • 不能用 reserve() 減少容器容量。為該目的提供的是 shrink_to_fit()。(文章后面有詳細的介紹)

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

shrink_to_fit

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

void shrink_to_fit();

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

具體的示例如下:

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函數主要用來擦除所有元素,使用clear()后,再次調用size(),size函數返回0。clear函數的聲明如下:

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

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

insert

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

//在 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 已經失效,提供新迭代器
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函數的聲明如下:

/*----------------------------------
  pos:將構造新元素到其前的迭代器
  args:轉發給元素構造函數的參數
  返回值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 起

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

earse

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

//移除位于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)中的元素。
/*返回值:最后移除元素之后的迭代器。
         如果在移除前last == 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}

// 移除所有偶數
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函數的主要作用是將元素添加到容器末尾,其聲明如下:

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

//后附給定元素 value 到容器尾。移動 value 進新元素。
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函數與emplace類似,只不過是在容器末尾就地構造元素,其函數聲明如下:

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是原地構造元素,因此其插入效率要高于push_back。

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

pop_back

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

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

如果在空容器上調用pop_back會導致未定義行為。

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

resize

resize函數的主要作用是改變容器中可存儲元素的個數,通過該函數可以重新設置容器大小,其函數聲明如下:

/*
該函數重設容器的大小為count,在count==size()時不做任何操作。
如果當前大小大于 count,那么減小容器到它的開頭 count 個元素。
如果當前大小小于 count,那么后附額外的默認插入的元素。
*/
void resize( size_type count ); //C++20 前
constexpr void resize( size_type count ); //C++20 起

/*
該函數重設容器的大小為count,在count==size()時不做任何操作。
如果當前大小大于 count,那么減小容器到它的開頭 count 個元素。
如果當前大小小于 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函數的主要作用是交換兩個vector容器的內容,不在單獨的元素上調用任何移動、復制或交換操作。所有迭代器和引用保持有效。end()迭代器會失效。其函數聲明如下:

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 < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';
//打印結果為2 5 1 4

a1.swap(a2);

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

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

2.2 非成員函數

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

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

//1. ==
//返回值:在 vector 內容相等時返回 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 內容不相等時返回 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 的內容按字典序小于 rhs 的內容時返回 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 的內容按字典序小于或等于 rhs 的內容時返回 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 的內容按字典序大于 rhs 的內容時返回 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 的內容按字典序大于或等于 rhs 的內容時返回 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的內容是相等,即他們是否擁有相同數量的元素且lhs中每個元素與rhs的相同位置元素比較相等。同時函數中T 必須符合 可相等比較(EqualityComparable) 的要求

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

  • 7中也是按字典序比較lhs和rhs的內容。其內部等價于調用std::lexicographical_compare_three_way進行比較。返回類型同合成三路比較的結果類型。其邏輯大致如下:

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

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

其具體的應用示例如下所示:

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';

輸出結果為

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)函數是為std::vector特化std::swap 算法。其函數聲明如下:

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 的內容。調用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';
// 打印結果為1 4 2 5

std::swap(a1, a2);

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

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

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

//從容器中擦除所有比較等于 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 的元素,其返回值為被擦除的元素個數,其等價于

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 的元素,其返回值為被擦除的元素個數,其等價于

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中的偶數
auto erased2 = std::erase_if(c, [](int n)
                             { return n % 2 == 0; }); // erased2 = 3
// 此時c = {1}

3. 總結

vector容器的優勢和劣勢:

優勢

  • 支持隨機訪問,訪問無開銷,時間恒定。
  • 線性遍歷/搜索。
  • 在容量滿足的情況下,末端插入元素效率高。

劣勢

  • 如果元素類型具有較高的復制/分配成本,則插入元素速度比較慢。
  • 如果隨之位置插入或擦除占程序的主導地位,程序會變慢。

vector容器在具體的應用中需要注意一下幾點:

  1. 創建一個新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中元素的數量
  • capacity()代表當前vector中可以存儲元素數量的最大值。
    如果在向vector中添加元素之前提前知道元素(大致的)數量n,及時使用resrve(n),這樣可以避免在元素插入階段可能產生的不必要內存分配和復制。
  1. 插入元素和擦除元素的效率
    在末尾插入元素的效率最快,但插入任意位置可能會很慢,因為中間可能涉及到元素的復制和移動。擦除元素同理。
  2. 使用shrink_to_fit()降低內存
    從vector中擦除元素不會改變其容量,因此未存放的元素的位置對應內存不會被釋放,如果后續不需要再使用這些空閑的內存,可以使用shrink_to_fit()對該內存進行釋放,提高內存使用效率。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲器
    +關注

    關注

    38

    文章

    7528

    瀏覽量

    164189
  • 交換機
    +關注

    關注

    21

    文章

    2656

    瀏覽量

    99997
  • 分配器
    +關注

    關注

    0

    文章

    195

    瀏覽量

    25808
  • C++語言
    +關注

    關注

    0

    文章

    147

    瀏覽量

    7021
  • 迭代器
    +關注

    關注

    0

    文章

    44

    瀏覽量

    4335
收藏 人收藏

    評論

    相關推薦

    c++vector容器

    1.vector容器介紹 ? ? ? 向量(Vector)是一個封裝了動態大小數組的順序容器(Sequence Container)。跟任意其它類型容器一樣,它能夠存放各種類型的對象。
    的頭像 發表于 07-13 19:36 ?1489次閱讀
    <b class='flag-5'>c++</b>之<b class='flag-5'>vector</b>容器

    C++教程之數組

    C++教程之數組 新版的成績管理系統編輯某同學的7門功課成績分別為:88,89,90,75,76,64,95。設計一個程序求其平均成績,并增加查詢功能:即用戶選擇1
    發表于 05-15 17:59 ?45次下載

    C++實驗 數組的應用

    C++實驗 數組的應用
    發表于 12-30 15:04 ?0次下載

    C++ vector刪除符合條件元素的編程技巧

    C++ vector中實際刪除元素使用的是容器vecrot中std::vector::erase()方法。 C++
    的頭像 發表于 09-20 10:03 ?5455次閱讀

    C++語言入門教程之C++語言程序設計數組的詳細資料概述免費下載

    本文檔的主要內容詳細介紹的是C++語言入門教程之C++語言程序設計數組的詳細資料概述免費下載內容包括了:1 一維數組 2 二維數組 3 字符
    發表于 09-20 14:51 ?9次下載
    <b class='flag-5'>C++</b>語言入門教程之<b class='flag-5'>C++</b>語言程序設計<b class='flag-5'>數組</b>的詳細資料概述免費下載

    C++程序設計教程之數組的詳細資料說明

    本文檔詳細介紹的是C++程序設計教程之數組的詳細資料說明主要內容包括了:1. 數組的概念,2. 一維數組的定義和引用,3. 二維數組的定義和
    發表于 03-14 14:48 ?10次下載
    <b class='flag-5'>C++</b>程序設計教程之<b class='flag-5'>數組</b>的詳細資料說明

    圖文詳解C++虛表的剖析

    圖文詳解C++虛表的剖析
    的頭像 發表于 06-29 14:23 ?2567次閱讀
    圖文<b class='flag-5'>詳解</b>:<b class='flag-5'>C++</b>虛表的剖析

    圖文詳解C++的輸出輸入

    圖文詳解C++的輸出輸入
    的頭像 發表于 06-29 14:53 ?3409次閱讀
    圖文<b class='flag-5'>詳解</b>:<b class='flag-5'>C++</b>的輸出輸入

    C++vector的定義與初始化

    C++中的vector vector(向量)是一種序列式容器,類似于數組,但比數組更優越。一般來說數組
    的頭像 發表于 02-02 16:41 ?9127次閱讀
    <b class='flag-5'>C++</b>中<b class='flag-5'>vector</b>的定義與初始化

    變長數組動態數組區別

    動態數組是指在聲明時,沒有確定數組大小的數組,它可以隨程序需要而重新指定大小。動態數組的內存空間
    的頭像 發表于 09-28 15:20 ?1974次閱讀

    C語言中的數組空間動態開辟

    C語言中的數組空間動態開辟 在C語言中,必不可少的需要使用到數組,通常為了動態的開辟
    的頭像 發表于 02-10 12:42 ?2212次閱讀

    C++入門之數組的概念

    上一篇文章我們介紹了C++中的迭代器,這篇文章將會介紹C++數組的概念,數組是一種和vector類似的數據結構,但是其在性能和靈活性上的權
    的頭像 發表于 03-17 14:14 ?719次閱讀

    C++ std::tie函數的作用和用法

    C++std::tie函數的作用就是從元素引用中生成一個tuple元組,其在頭文件中定義
    的頭像 發表于 07-18 17:28 ?881次閱讀

    ?數組C++ std::array詳解

    std::array是C++容器庫提供的一個固定大小數組的容器。其與內置的數組相比,是一種更安全、更容易使用的數組類型。
    的頭像 發表于 07-19 11:02 ?1156次閱讀
    ?<b class='flag-5'>數組</b>和<b class='flag-5'>C++</b> <b class='flag-5'>std</b>::array<b class='flag-5'>詳解</b>

    C++數組名和數組拷貝詳解

    C++數組間賦值不能直接通過數組名稱 randy = sesame進行,因為數組名并不是指針,大部分情況下,編譯器會隱式轉換為指向數組首元素
    發表于 08-21 15:09 ?482次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>數組</b>名和<b class='flag-5'>數組</b>拷貝<b class='flag-5'>詳解</b>
    主站蜘蛛池模板: 国产a视频视卡在线 | 在线观看国产高清免费不卡 | 2017必看无码作品 | 亚洲精品中文字幕无码A片蜜桃 | 精品人妻无码一区二区三区蜜桃臀 | 无码人妻99久久密AV | 日本精品久久久久中文字幕2 | 姑娘视频日本在线播放 | 纯肉宠文高h一对一 | 久久国产加勒比精品无码 | 亚洲一卡二卡三卡四卡无卡麻豆 | 国产精品系列在线观看 | 久久综合老色鬼网站 | 成人亚洲视频在线观看 | 大学生高潮无套内谢视频 | 亚洲精品动漫免费二区 | 久久99久久成人免费播放 | 中文字幕人成人乱码亚洲影视 | 中国老太太xxx| 国产剧情福利AV一区二区 | 麻豆精选2021 | 亚洲国产中文字幕在线视频 | 国产精品久久久久久久久齐齐 | 欧美日韩在线成人看片a | 亚洲中文字幕日本在线观看 | 久久久久夜 | www.欧美与曽交性video | 亚洲综合免费视频 | 偷拍精品视频一区二区三区 | 精品 在线 视频 亚洲 | 久久AV国产麻豆HD真实乱 | 韩国伦理三级 | 哒哒哒高清视频在线观看 | 91九色视频在线观看 | 91福利潘春春在线观看 | 色播播电影 | 久久视频这里只精品99热在线观看 | 国产欧洲野花A级 | 少妇高潮A片特黄久久精品网 | 色欲久久精品AV无码 | 在线观看亚洲专区5555 |