2015-11-03 59 views
23

std::beginstd::end知道containerarray的開始和結束。std :: end如何知道數組的結尾?

例如,它很容易知道endbeginvector,因爲它是提供此信息的類。但是,它如何知道如下所示的array的結束?

int simple_array[5]{1, 2, 3, 4, 5}; 
auto beg=std::begin(simple_array); 
auto en=std::end(simple_array); 

std::begin是不是很難知道從哪裏數組開始。但它是如何知道它結束的?將整數5存儲在什麼地方?

如果我有一些低級信息的答案,我將不勝感激。

回答

22

是常量整數5將存儲在哪裏?

是的,它是數組類型的一部分。但是,不,它沒有明確地存儲在任何地方。當你有

int i[5] = { }; 

i類型爲int[5]。 Shafik的回答談到如何使用這個長度來實現end

如果你一直C++ 11,使用constexpr將是簡單的路要走

template <typename T, size_t N> 
inline constexpr size_t 
arrLen(const T (&arr) [N]) { 
    return N; 
} 

如果你已經預先C++編譯器11,其中constexpr不可用,上述函數可能不會在編譯時進行評估。所以在這種情況下,可以使用這樣的:

template <typename T, size_t N> 
char (&arrLenFn(const T (&arr) [N]))[N]; 

#define arrLen(arr) sizeof(arrLenFn(arr)) 

首先聲明一個函數返回一個參考N個char小號即sizeof陣列這個函數現在將是陣列的長度。然後我們有一個宏來包裝它,以便在調用者的最後可讀。

注意:兩個相同基本類型但長度不同的數組仍然是兩種完全不同的類型。 int[3]int[2]不一樣。然而,在兩種情況下,Array decay都會給你一個int*。如果您想了解更多信息,請閱讀How do I use arrays in C++?

+0

謝謝,看來我錯過了很多東西..我應該問「什麼是數組」。你的意思是說,該數組是一種小指針開始的指針和一些元素?你能指出我可以詳細閱讀嗎? –

+2

具有相同基本類型但長度不同的兩個數組仍然是兩種完全不同的類型。 'int [3]'與'int [2]'不一樣。然而,在這兩種情況下,數組衰減會給你一個'int *'。閱讀[如何在C++中使用數組?](http://stackoverflow.com/q/4810664/183120),如果想知道更多的數組。 – legends2k

+0

是的,這正是我從你的答案中得出的結論。再次感謝 –

24

但是,它是如何知道數組

它使用一個模板非類型參數推斷出該陣列,然後其可用於生產最終指針的大小的結束。從cppreference部分中的C++ 11簽名std::end如下:

template< class T, std::size_t N > 
T* end(T (&array)[N]); 

作爲HVD音符,因爲它是通過引用傳遞這防止衰變到一個指針。

的實施將是類似於:

template< class T, std::size_t N > 
T* end(T (&array)[N]) 
{ 
    return array + N ; 
} 

是常量整數5將存儲一些在哪裏?

5N是陣列的類型的一部分,因此N可在編譯時。例如,將sizeof應用於數組會給我們數組中的總字節數。

很多時候我們看到一個數組通過值傳遞給函數。在這種情況下,數組decays to a pointer可以存儲在數組中。所以現在尺寸信息丟失了。通過引用傳遞可以避免這種信息丟失,並從類型中提取大小N

+0

謝謝,這是否意味着N存儲在某個地方?如果是的話,在哪裏? –

+0

N由函數存儲。一旦函數執行完成,它就會丟失。如果你想達到相同的效果,並返回數組的大小,你可以使用這個答案中提供的代碼,並返回N. –

+0

@HumamHelfawi你知道我錯過了你的評論前面的點,並意識到,當我通勤你意思。我更新了我的答案,正確地覆蓋了您的評論。 –

7

因爲您將數組傳遞給std::end,並且數組的類型爲T [N]std::end可以通過查看類型中的N來判斷數組何時結束。

相關問題