1. 數(shù)組和std::array
std::array
是C++容器庫提供的一個(gè)固定大小數(shù)組的容器。其與內(nèi)置的數(shù)組相比,是一種更安全、更容易使用的數(shù)組類型。std::array
在頭文件中定義,其聲明如下:
template<
class T,
std::size_t N
> struct array; //C++11 起
std::array
是一個(gè)聚合類型,其語義等同于保有一個(gè)C語言風(fēng)格數(shù)組T[N]
作為其唯一非靜態(tài)數(shù)據(jù)成員的結(jié)構(gòu)體,但其不同于C數(shù)組的是它不會自動退化為T*
。同時(shí)該結(jié)構(gòu)體結(jié)合了C風(fēng)格數(shù)組的性能、可訪問性和容器的優(yōu)點(diǎn)(可獲取大小、支持賦值和隨機(jī)訪問等)。
2. array的用法
2.1 成員函數(shù)
2.1.1 隱式定義的成員函數(shù)
聚合初始化就是從初始化器列表來初始化聚合體,其也是列表初始化的一種方式。
std::array< int, 3 > a = {1,2,3};
std::array< int, 3 > b;
b = a; //將a中的每個(gè)元素重寫到b中,使用operator=時(shí)候需要確保a b兩個(gè)容器長度相等,否則編譯失敗
2.1.2 元素訪問
at
at用于訪問指定的元素, 同時(shí)進(jìn)行越界檢查 ,該函數(shù)返回位于指定位置pos的元素的引用,如果pos不在容器的范圍內(nèi),則拋出std::out_of_range
異常。其函數(shù)聲明如下:
reference at( size_type pos ); //C++17 前
constexpr reference at( size_type pos ); //C++17 起
const_reference at( size_type pos ) const; //C++14 前
constexpr const_reference at( size_type pos ) const; //C++14 起
其具體用法如下:
std::array< int,3 > data = { 1, 2, 3};
std::cout<
operator[]
operator[]與at功能相同,即用來訪問指定的元素,但其與at不同的是:operator[]不進(jìn)行邊界的檢查。其函數(shù)聲明如下所示:
reference operator[]( size_type pos ); //C++17 前
constexpr reference operator[]( size_type pos ); //C++17 起
const_reference operator[]( size_type pos ) const; //C++14 前
constexpr const_reference operator[]( size_type pos ) const; //C++14 起
注 :通過operator[]符訪問不存在的元素是未定義行為。
front
front用于訪問容器的第一個(gè)元素,其返回值為容器首元素的引用,其函數(shù)原型如下:
reference front(); //C++17 前
constexpr reference front(); //C++17 起
const_reference front() const; //C++14 前
constexpr const_reference front() const; //C++14 起
注 :在空容器上對
front
的調(diào)用是未定義的。
back
back主要功能是用來訪問容器最后一個(gè)元素,其返回值為容器最后一個(gè)元素的引用,其函數(shù)原型如下所示:
reference back(); //C++17 前
constexpr reference back(); //C++17 起
const_reference back() const; //C++14 前
constexpr const_reference back() const; //C++14 起
注 :在空容器上調(diào)用
back
導(dǎo)致未定義行為。
data
data可以直接訪問容器底層數(shù)組,其返回值為指向作為元素存儲工作的底層數(shù)組的指針。其函數(shù)聲明如下:
T* data() noexcept; //C++11 起, C++17 前
constexpr T* data() noexcept; //C++17 起
const T* data() const noexcept; //C++11 起, C++17 前
constexpr const T* data() const noexcept; //C++17 起
其返回的指針使得范圍[ data()
, data() + size()
)始終是合法范圍。
2.2.3 迭代器
begin、end和cbegin、cend
begin和cbegin返回指向deque首元素的迭代器,end和cend返回指向deque末元素后一元素的迭代器。其函數(shù)聲明如下:
iterator begin() noexcept; //C++17 前
constexpr iterator begin() noexcept; //C++17 起
const_iterator begin() const noexcept; //C++17 前
constexpr const_iterator begin() const noexcept; //C++17 起
const_iterator cbegin() const noexcept; //C++17 前
constexpr const_iterator cbegin() const noexcept; //C++17 起
iterator end() noexcept; //C++17 前
constexpr iterator end() noexcept; //C++17 起
const_iterator end() const noexcept; //C++17 前
constexpr const_iterator end() const noexcept; //C++17 起
const_iterator cend() const noexcept; //C++17 前
constexpr const_iterator cend() const noexcept; //C++17 起
如果array為空,則返回的迭代器將等于end或cend。end和cend指向deque末元素后一元素的迭代器,該元素的表現(xiàn)為占位符,試圖訪問它將導(dǎo)致未定義行為。
rbegin、rend和crbegin、crend
rbegin和crbegin返回指向array首元素的逆向迭代器。它對應(yīng)非逆向array的末元素,若array為空,則返回的迭代器等于rend或crend。rend和crend返回指向逆向deque末元素后一元素的逆向迭代器,它對應(yīng)非逆向array首元素的前一元素,此元素表現(xiàn)為占位符,試圖訪問它導(dǎo)致未定義行為。它們的聲明如下:
reverse_iterator rbegin() noexcept; //C++17 前
constexpr reverse_iterator rbegin() noexcept; //C++17 起
const_reverse_iterator rbegin() const noexcept; //C++17 前
constexpr const_reverse_iterator rbegin() const noexcept; //C++17 起
const_reverse_iterator crbegin() const noexcept; //C++17 前
constexpr const_reverse_iterator crbegin() const noexcept; //C++17 起
reverse_iterator rend(); //C++11 前
reverse_iterator rend() noexcept; //C++11 起
const_reverse_iterator rend() const; //C++11 前
const_reverse_iterator rend() const noexcept; //C++11 起
const_reverse_iterator crend() const noexcept; //C++11 起
2.2.4 容量
empty
empty用來檢查容器是否為空,若為空則返回true,否則為false。其函數(shù)聲明如下:
constexpr bool empty() const noexcept; //C++11 起,C++20 前
[[nodiscard]] constexpr bool empty() const noexcept; //C++20 起
其底層實(shí)現(xiàn)就是檢查容器是否無元素,即判斷是否begin() == end()
。
size
size函數(shù)返回容器中元素?cái)?shù)量,即std::distance(begin(), end())
。其函數(shù)聲明如下:
constexpr size_type size() const noexcept; //C++11 起
max_size
max_size函數(shù)返回根據(jù)系統(tǒng)或庫實(shí)現(xiàn)限制的容器可保有的元素最大數(shù)量,即對于最大容器的 std::distance(begin(), end())
。其函數(shù)聲明為:
constexpr size_type max_size() const noexcept; //C++11 起
注 :因?yàn)槊總€(gè)
std::array
都是固定大小容器,故max_size
返回的值等于N
(亦為size所返回的值)
2.2.5 修改器
fill
fill函數(shù)原型如下所示:
void fill( const T& value ); //C++11 起, C++20 前
constexpr void fill( const T& value ); //C++20 起
fill函數(shù)主要用于以指定值填充容器,即將定值 value
賦給容器中的所有元素。
具體用法示例如下:
std::array< int, 3 > arr = {1, 2, 3};
arr.fill(1); // arr = {1, 1, 1}
swap
swap函數(shù)的主要作用是交換兩個(gè)array容器的內(nèi)容,其與deque的swap不同的是不導(dǎo)致迭代器和引用關(guān)聯(lián)到別的容器。其函數(shù)聲明如下:
void swap( array& other ) noexcept(); //C++11 起, C++20 前
constexpr void swap( array& other ) noexcept(); //C++20 起
其用法示例如下圖所示:
std::array< 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
a1.swap(a2);
// 此時(shí)a1 = {4, 5, 6},a2 = {1, 2, 3}
std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';
// 打印結(jié)果為4 1 5 2
/*注:
交換后迭代器與引用保持與原 array 關(guān)聯(lián),
例如it1仍指向元素 a1[0] ,ref1仍指代 a1[1] */
2.2 非成員函數(shù)
operator==,!=,<,<=,>,>=,<=>(std::array)
C++提供operator==,!=,<,<=,>,>=,<=>(std::array)
非成員函數(shù)用來比較兩個(gè)array的大小,相關(guān)函數(shù)及函數(shù)聲明如下:
//1. ==
//返回值:在 array 內(nèi)容相等時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator==( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
template< class T, std::size_t N >
constexpr bool operator==( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 起
//2. !=
//返回值:在 array 內(nèi)容不相等時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator!=( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
//3. <
//返回值:在 lhs 的內(nèi)容按字典序小于 rhs 的內(nèi)容時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator< ( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
//4. <=
//返回值:在 lhs 的內(nèi)容按字典序小于或等于 rhs 的內(nèi)容時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator<=( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
//5. >
//返回值:在 lhs 的內(nèi)容按字典序大于 rhs 的內(nèi)容時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator >( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
//6. >=
//返回值:在 lhs 的內(nèi)容按字典序大于或等于 rhs 的內(nèi)容時(shí)返回 true,否則返回 false
template< class T, std::size_t N >
bool operator >=( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 前
//7. <= >
//返回值:lhs 與 rhs 中的首對不等價(jià)元素的相對順序,如果有這種元素;否則是 lhs.size() <= > rhs.size()。
template< class T, std::size_t N >
constexpr operator<= >( const std::array< T, N >& lhs,
const std::array< T, N >& rhs ); //C++20 起
1,2中會檢查lhs和rhs的內(nèi)容是相等,即他們是否擁有相同數(shù)量的元素且lhs中每個(gè)元素與rhs的相同位置元素比較相等。同時(shí)函數(shù)中
T
必須符合 可相等比較(EqualityComparable) 的要求3-6中按照字典比較lhs和rhs的內(nèi)容,其內(nèi)部等價(jià)于調(diào)用
std::lexicographical_compare
函數(shù)進(jìn)行比較。同時(shí)函數(shù)中T
必須符合[ 可小于比較(LessThanComparable) 的要求。7中也是按字典序比較lhs和rhs的內(nèi)容。其內(nèi)部等價(jià)于調(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中的首對不等價(jià)元素的相對順序,如果有這種元素;否則是
lhs.size() <=> rhs.size()
。
其具體的應(yīng)用示例如下所示:
std::array< int, 3 > alice{1, 2, 3};
std::array< int, 3 > bob{7, 8, 9};
std::array< int, 3 > 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::get(std::array)
std::get(std::array)
可以用來訪問array的一個(gè)元素,其函數(shù)聲明如下:
template< std::size_t I, class T, std::size_t N >
T& get( std::array< T,N >& a ) noexcept; //C++11 起, C++14 前
template< std::size_t I, class T, std::size_t N >
constexpr T& get( std::array< T,N >& a ) noexcept; //C++14 起
template< std::size_t I, class T, std::size_t N >
T&& get( std::array< T,N >&& a ) noexcept; //C++11 起, C++14 前
template< std::size_t I, class T, std::size_t N >
constexpr T&& get( std::array< T,N >&& a ) noexcept; //C++14 起
template< std::size_t I, class T, std::size_t N >
const T& get( const std::array< T,N >& a ) noexcept; //C++11 起, C++14 前
template< std::size_t I, class T, std::size_t N >
constexpr const T& get( const std::array< T,N >& a ) noexcept; //C++14 起
template< std::size_t I, class T, std::size_t N >
const T&& get( const std::array< T,N >&& a ) noexcept; //C++11 起, C++14 前
template< std::size_t I, class T, std::size_t N >
constexpr const T&& get( const std::array< T,N >&& a ) noexcept; //C++14 起
其主要作用是從a
中提取第I
個(gè)元素.I
必須是范圍 [0, N)
中的整數(shù)值。與at()
或 operator[]
相反,這在編譯時(shí)強(qiáng)制。該函數(shù)的返回值為a
中第I
元素的引用。
其具體的用法如下:
std::array< int, 3 > arr;
// 設(shè)置值:
std::get< 0 >(arr) = 1;
std::get< 1 >(arr) = 2;
std::get< 2 >(arr) = 3;
// 獲取值:
std::cout < < "(" < < std::get< 0 >(arr) < < ", " < < std::get< 1 >(arr)
< < ", " < < std::get< 2 >(arr) < < ")n";
//輸出結(jié)果為 (1, 2, 3)
std::swap(std::array)
std::swap(std::array)
函數(shù)是為std::array
特化std::swap
算法。其函數(shù)聲明如下:
template< class T, std::size_t N >
void swap( std::array< T, N >& lhs,
std::array< T, N >& rhs ); //C++11 起, C++17 前
template< class T, std::size_t N >
void swap( std::array< T, N >& lhs,
std::array< T, N >& rhs ) noexcept(); //C++17 起, C++20 前
template< class T, std::size_t N >
constexpr void swap( std::array< T, N >& lhs,
std::array< T, N >& rhs ) noexcept(); //C++20 起
交換 lhs
與 rhs
的內(nèi)容。調(diào)用lhs.swap(rhs)
。其具體用法如下:
std::array< 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);
// 此時(shí)a1 = {4, 5, 6},a2 = {1, 2, 3}
std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';
// 打印結(jié)果為4 1 5 2
std::to_array
std::to_array
函數(shù)聲明如下:
template< class T, std::size_t N >
constexpr std::array< std::remove_cv_t< T >, N > to_array(T (&a)[N]); //C++20 起
template< class T, std::size_t N >
constexpr std::array< std::remove_cv_t< T >, N > to_array(T (&&a)[N]); //C++20 起
std::to_array
函數(shù)可以從一維內(nèi)建數(shù)組 a
創(chuàng)建 std::array
對象,從 a
的對應(yīng)元素復(fù)制初始化 std::array
的元素。不支持復(fù)制或移動多維內(nèi)建數(shù)組。其具體用法如下:
#include < array >
#include < iostream >
int main()
{
// 復(fù)制字符串字面量
auto a1 = std::to_array("foo");
static_assert(a1.size() == 4);
// 推導(dǎo)元素類型和長度
auto a2 = std::to_array({0, 2, 1, 3});
// 推導(dǎo)長度而元素類型指定
// 發(fā)生隱式轉(zhuǎn)換
auto a3 = std::to_array< long >({0, 1, 3});
auto a4 = std::to_array< std::pair< int, float >>(
{{3, .0f}, {4, .1f}, {4, .1e23f}});
// 創(chuàng)建不可復(fù)制的 std::array
auto a5 = std::to_array({std::make_unique< int >(3)});
// 錯(cuò)誤:不支持復(fù)制多維數(shù)組
// char s[2][6] = { "nice", "thing" };
// auto a6 = std::to_array(s);
}
std::tuple_size
std::tuple_size(std::array)
函數(shù)的聲明如下:
template< class T, std::size_t N >
struct tuple_size std::array< T, N > > :
std::integral_constant< std::size_t, N > //C++11 起
{ };
其提供作為編譯時(shí)常量表達(dá)式訪問std::array
中元素?cái)?shù)量的方法。用法示例如下:
#include < iostream >
#include < array >
template< class T >
void test(T t)
{
int a[std::tuple_size< T >::value]; // 能用于編譯時(shí)
std::cout < < std::tuple_size< T >::value < < 'n';
}
int main()
{
std::array< float, 3 > arr;
test(arr); //輸出 3
}
std::tuple_element
std::tuple_element
函數(shù)主要用來獲得 array
元素的類型,其聲明如下:
template< std::size_t I, class T, std::size_t N >
struct tuple_element I, std::array< T, N > >; //C++11 起
其使用類 tuple 接口,提供 array 元素類型的編譯時(shí)帶下標(biāo)訪問。具體使用方法如下:
// 定義 array 并獲取位于位置 0 的元素類型
std::array< int, 10 > data {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
using T = std::tuple_element< 0, decltype(data) >::type; // int
3. 總結(jié)
數(shù)組std::array
的優(yōu)劣:
優(yōu)點(diǎn)
- 無開銷隨機(jī)訪問。
- 快速遍歷;適合線性搜索。
劣勢
- 如果元素類型具有較高的復(fù)制/分配成本,則可能會變慢(重新排序元素需要復(fù)制/移動它們)。
- 在使用array容器的時(shí)候,其size必須是常量表達(dá)式(即編譯時(shí)已知)。
- 不支持大小更改操作(調(diào)整大小、插入、擦除等)。
-
存儲器
+關(guān)注
關(guān)注
38文章
7484瀏覽量
163759 -
交換機(jī)
+關(guān)注
關(guān)注
21文章
2637瀏覽量
99528 -
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136680 -
C++語言
+關(guān)注
關(guān)注
0文章
147瀏覽量
6987 -
迭代器
+關(guān)注
關(guān)注
0文章
43瀏覽量
4307
發(fā)布評論請先 登錄
相關(guān)推薦
評論