簡體   English   中英

用C ++聲明數組

[英]Declaring arrays in C++

我是C ++的新手,目前正在自己​​學習一本書。 這本書似乎說有幾種數組取決於你如何聲明它。 我想動態數組和靜態數組之間的區別對我來說很清楚。 但我不明白STL std::array類和靜態數組之間的區別。

STL std::array變量聲明為:

std::array < int, arraySize > array1;

而靜態數組變量聲明為:

int array1[arraySize];

這兩者之間有根本的區別嗎? 或者它只是語法而兩者基本相同?

std::array<>只是C風格數組的一個輕量級包裝器,帶有一些額外的好的接口成員函數(如beginend等)和typedef s,大致定義為

template<typename T, size_t N>
class array
{
public:
    T _arr[N];
    T& operator[](size_t);
    const T& operator[](size_t) const;
    // other member functions and typedefs
}

但是一個基本的區別是前者可以通過值傳遞,而后者只能傳遞指向第一個元素的指針,或者你可以通過引用傳遞它,但是你不能將它復制到函數中(除了通過std::copy或手動)。

一個常見的錯誤是假設每次將C樣式數組傳遞給函數時,由於數組衰減為指針而導致其大小丟失。 這並非總是如此。 如果您通過引用傳遞它,則可以恢復其大小,因為在這種情況下沒有衰減:

#include <iostream>

template<typename T, size_t N>
void f(T (&arr)[N]) // the type of arr is T(&)[N], not T*
{
    std::cout << "I'm an array of size " << N;
}

int main()
{
    int arr[10];
    f(arr); // outputs its size, there is no decay happening
}

住在Coliru

這兩者之間的主要區別是重要的。

除了STL給你的好方法,在將std::array傳遞給函數時,沒有衰減。 意思是,當你在函數中收到std::array時,它仍然是一個std::array ,但是當你將一個int[]數組傳遞給一個函數時,它會有效地衰減到一個int*指針和數組的大小迷路了。

這種差異是一個重要的差異。 一旦丟失了數組大小,代碼現在容易出現很多錯誤,因為您必須手動跟蹤數組大小。 sizeof()返回指針類型的大小,而不是數組中元素的數量。 這會強制您使用process(int *array, int size)等接口手動跟蹤數組大小。 這是一個很好的解決方案,但容易出錯。

請參閱Bjarne Stroustroup的指南:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rp-run-time

使用更好的數據類型可以避免這種情況, std::array是為許多其他STL類設計的。

作為旁注,除非有充分的理由使用固定大小的數組,否則std::vector可能是一個更好的選擇作為連續的內存數據結構。

std::array和C風格的數組類似:

  • 它們都存儲連續的對象序列
  • 它們都是聚合類型,因此可以使用聚合初始化進行初始化
  • 它們的大小在編譯時是已知的
  • 它們不使用動態內存分配

std::array一個重要優點是它可以通過值傳遞,並且不會像C風格的數組那樣隱式衰減到指針。

在這兩種情況下,都會在堆棧上創建數組。

但是,STL的std::array類模板比第二種情況的“原始”C類數組語法提供了一些優勢:

 int array1[arraySize]; 

例如,對於std::array您有一個典型的STL接口,使用size (可用於查詢數組的元素計數), frontbackat等方法。

你可以在這里找到更多細節。

這兩者之間有根本的區別嗎? 或者它只是語法而兩者基本相同?

原始c風格數組( 內置數組 )與std::array

從參考文檔中可以看出,有許多可用的操作沒有原始數組:

例如:元素訪問

at()
front()
back()
data()

std::array的底層數據類型仍然是一個原始數組,但是帶有“語法糖” (如果這應該是您關注的話)。

std::array<>和C風格數組的主要區別在於前者是一個包裹后者的類。 該類有begin()end()方法,允許std::array對象作為參數輕松傳入期望迭代器的STL算法(注意C樣式數組也可以通過非成員std::begin / std::end方法)。 第一個指向數組的開頭,第二個指向超出其結束的一個元素。 您可以使用其他STL容器看到此模式,例如std::vectorstd::mapstd::set等。

STL std::array另一個std::array是它有一個size()方法,可以讓你獲得元素數。 要獲得C風格數組的元素數,您必須編寫sizeof(cArray)/sizeof(cArray[0]) ,所以stlArray.size()看起來不那么可讀嗎?

你可以在這里得到完整的參考:

http://en.cppreference.com/w/cpp/container/array

通常你應該更喜歡std::array<T, size> array1; 超過T array2[size]; 但是,底層結構是相同的。

主要原因是std::array總是知道它的大小。 您可以調用其size()方法來獲取大小。 而當你使用C風格的數組(即你所謂的“內置數組”)時,你總是必須將大小傳遞給使用該數組的函數。 如果你以某種方式弄錯了,你可能會導致緩沖區溢出,並且該函數會嘗試讀取/寫入不再屬於該數組的內存。 std::array不會發生這種情況,因為大小始終是清晰的。

IMO,

  • 優點:它的效率很高,因為它不會使用比內置固定陣列更多的內存。

  • 缺點:內置固定數組上的std::array是一種稍微笨拙的語法,你必須明確指定數組長度(編譯器不會從初始化程序中為你計算它)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM