先請各位看看代碼,思考一下,這里的代碼是做什么的?
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];//沒有定義,只做了聲明
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _MSC_VER
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
#define arraysize(array) (sizeof(ArraySizeHelper(array)))

int a[10]
int size = arraysize(a);//這里能夠求出a的大小

這個代碼比普通的sizeof(a)/sizeof(int)更安全,它避免了我們做這樣的操作:
int a[10]
int *p = a;

int size = arraysize(p);//不可行
size = arraysize(a);//可行
利用模板獲得一個數組的引用,返回對應的char類型的數組引用再對char類型的數組求大小,不用求sizeof(T),代替了了除法運算和兩次求值sizeof(),不知道這個會不會影響編譯時的效率
根
template <typename T, size_t N>
char (*ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(*ArraySizeHelper(array)))
據waiting4you的評論,也可以這樣做:
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];//沒有定義,只做了聲明
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _MSC_VER
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
int a[10]
int size = arraysize(a);//這里能夠求出a的大小
這個代碼比普通的sizeof(a)/sizeof(int)更安全,它避免了我們做這樣的操作:
int a[10]
int *p = a;
int size = arraysize(p);//不可行
size = arraysize(a);//可行
根
template <typename T, size_t N>
char (*ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(*ArraySizeHelper(array)))
對于老的編譯器,不允許返回數組的引用,但是返回指針數組應該是沒有問題的,入口參數傳遞數組的引用也沒有問題

這個用法在 <<Imperfect C++>> 中有說明, 并不是什么新東西. 也不是為了提高速度, 而是為了更安全, 對于重載了 operator[] 的自定義對象, 退化成指針的數組這些, sizeof(a)/sizeof(a[0]) 可能產生錯誤的結果. 詳見 <<Imperfect C++>> 第 14 章 2, 3 節.
并且, Imperfect C++ 中并不推薦這種用法, 而是由另外的方法, 因為這種用法對編譯器的兼容性不好, 原文如下:
I should point out there's a slightly shorter (albeit harder to decipher) way to implement dimensionof(), as follows:
template<typename T, int N>
byte_t (&byte_array_of_same_dimension_as(T (&)[N]))[N];
#define dimensionof(x) sizeof(byte_array_of_same_dimension_as((x)));
Unfortunately this is recognized by fewer compilers[6] so I recommend the first form.
這個的關鍵是類型安全
原本我也認為他對指針可以求出數組自身的大小,但是原理上似乎行不通,因為即使拿到一個引用,也是引用了指向數組的指針的引用,并沒有引用到數組本身。編譯器的sizeof是在編譯期求的。你說的第二點應該是它的目的之一
int a[10];
int* p = a;
int size = arraysize(a);
所以sizeof的形式安全一些,sizeof(p)/sizeof(p[0])得到的是一個錯誤的結果。
另外敲起代碼來會快那么一點點
//
// RtlpNumberOf is a function that takes a reference to an array of N Ts.
//
// typedef T array_of_T[N];
// typedef array_of_T &reference_to_array_of_T;
//
// RtlpNumberOf returns a pointer to an array of N chars.
// We could return a reference instead of a pointer but older compilers do not accept that.
//
// typedef char array_of_char[N];
// typedef array_of_char *pointer_to_array_of_char;
//
// sizeof(array_of_char) == N
// sizeof(*pointer_to_array_of_char) == N
//
// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
//
// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
// We do not even implement RtlpNumberOf, we just decare it.
//
// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
// That is the point.
//
extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
...
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V2(A)
...
#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A)
恩,看了你的評論,又增長了一些知識