先請(qǐng)各位看看代碼,思考一下,這里的代碼是做什么的?
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的大小

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

int size = arraysize(p);//不可行
size = arraysize(a);//可行
利用模板獲得一個(gè)數(shù)組的引用,返回對(duì)應(yīng)的char類型的數(shù)組引用再對(duì)char類型的數(shù)組求大小,不用求sizeof(T),代替了了除法運(yùn)算和兩次求值sizeof(),不知道這個(gè)會(huì)不會(huì)影響編譯時(shí)的效率
根
template <typename T, size_t N>
char (*ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(*ArraySizeHelper(array)))
據(jù)waiting4you的評(píng)論,也可以這樣做:
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的大小
這個(gè)代碼比普通的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)))
對(duì)于老的編譯器,不允許返回?cái)?shù)組的引用,但是返回指針數(shù)組應(yīng)該是沒有問題的,入口參數(shù)傳遞數(shù)組的引用也沒有問題

這個(gè)用法在 <<Imperfect C++>> 中有說明, 并不是什么新東西. 也不是為了提高速度, 而是為了更安全, 對(duì)于重載了 operator[] 的自定義對(duì)象, 退化成指針的數(shù)組這些, sizeof(a)/sizeof(a[0]) 可能產(chǎn)生錯(cuò)誤的結(jié)果. 詳見 <<Imperfect C++>> 第 14 章 2, 3 節(jié).
并且, Imperfect C++ 中并不推薦這種用法, 而是由另外的方法, 因?yàn)檫@種用法對(duì)編譯器的兼容性不好, 原文如下:
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.
這個(gè)的關(guān)鍵是類型安全
原本我也認(rèn)為他對(duì)指針可以求出數(shù)組自身的大小,但是原理上似乎行不通,因?yàn)榧词鼓玫揭粋€(gè)引用,也是引用了指向數(shù)組的指針的引用,并沒有引用到數(shù)組本身。編譯器的sizeof是在編譯期求的。你說的第二點(diǎn)應(yīng)該是它的目的之一
int a[10];
int* p = a;
int size = arraysize(a);
所以sizeof的形式安全一些,sizeof(p)/sizeof(p[0])得到的是一個(gè)錯(cuò)誤的結(jié)果。
另外敲起代碼來會(huì)快那么一點(diǎn)點(diǎn)
//
// 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)
恩,看了你的評(píng)論,又增長(zhǎng)了一些知識(shí)