這個問題可簡單描述為:
給定乙個c++ 陣列(如:int x[10]),如何獲取它的元素個數?
一種顯而易見的方法是使用巨集(定義1):
#define countof( array ) (sizeof( array )/sizeof( array[0
]))
我不能說這種方法不正確,因為在給定乙個陣列,他確實能獲取其元素個數。然而,當提供的物件不是陣列時,同樣的表示式會給你一些不真實的結果。例如,如果你提供
int* p;
這時當執行在int指標和int擁有相同大小(如win32平台)機器上,countof( p )總是返回1。
這種巨集表示也可以錯誤接受任何有operator方法的類物件。例如,假設你寫的**如下:
class intarray x;
此時,sizeof(x)將返回x物件的大小,而不是x.p指向buffer的大小。因此,通過countof(x),你將不能獲取正確值。
所以我們可以斷言定義1不是一種好的方法,因為編譯器不能阻止你錯用它。它不能強制只傳遞陣列。
有沒有更好的選擇呢?
是的,如果我們希望編譯器保證coutof的引數總是陣列,我們必須找到乙個只允許陣列的上下文,且同時必須拒絕所有非陣列的表示式。
一些初學者可能嘗試這樣(定義2):
template
size_t countof(t array[n])
他們認為,這個模板函式將接受大小為n的陣列,並返回n。
不幸的是,這將編譯不過,因為c++對待陣列形參等同於指標引數,也就是上述的定義等同於:
template
size_t countof(t* array)
現在顯然函式主體沒方法知道n是多少。
然而,如果傳入的引數是陣列引用,此時編譯器保證實參的大小匹配形參。這意味我們小改定義2,使其工作(定義3):
template
size_t countof(t (&array)[n])
這個countof能工作很好,且你不能傳遞指標引數。但是,它是個函式,而不是巨集。這意味著你不能用它作為編譯常數。尤其,你不能寫**如下:
int
x[10];
inty[2
*countof(x)];
我們還有其他方法嗎?
有人(我不知道具體是誰)提出更好的主意:
從函式主體移出n至返回型別,此時我們能獲取n,而不需要實際呼叫函式。
確切地說,我們必須讓函式返回乙個陣列引用,因為c ++不允許直接返回陣列。
具體實現:
template char (&_arraysizehelper(t(&array)[n]))[n];
#define
countof(array) (sizeof(_arraysizehelper(array)))
不可否認,語法看起來很糟糕。事實上,有必要做一些解釋。
首先,頂層的表述
char (&_arraysizehelper(...))[n];
表示「_arraysizehelper是返回大小為n的char陣列引用的函式」。
而後,函式引數是
t (&array)[n]
表示引用元素個數為n的t陣列。
最後,coutof被定義為函式_arraysizehelper返回值大小。注意我們沒必要定義_arraysizehelper(),一宣告足矣。
利用新的定義,
int x[10];
int y[2*countof(x)]; //twice as big as x
正如我們希望的,變為有效定義。 如何獲取元素
1 通過elementid獲取元素 引用自 autocad revit二次開發基礎教程 並通過自我編輯 已知levelid,通過id獲取元素,確認後進行其他操作 private void useelementidandgetelement document doc 2 通過element filte...
12 9 2獲取鍊錶元素個數
鍊錶中往往會儲存大量的資料內容,同時鍊錶的本質有相當於乙個陣列,那麼為了可以準確的獲取資料的個數,就需要在鍊錶中進行資料的統計操作。1 ilink 在介面中定義乙個size 方法用於返回資料儲存的個數 獲取鍊錶中集合元素的儲存個數 return 元素個數 public int size 2 link...
C DataGridView如何獲取某個資料
datagridview的幾個基本操作 1.獲取某個 指定的 單元格的值 datagridview1.row i cells j value 2.獲取選中的總行數 datagridview1.selectedrows.count 3.獲取當前選中行的索引 datagridview1.currentr...