我们一般在程序中计算数组类型变量的大小通过定义如下的一个宏实现,如NUM_ELEMENTS定义:#define NUM_ELEMENTS(x) (sizeof((x))/sizeof((x)[0]))
该宏在计算正确的数组类型变量时不存在问题,但应用到指针上或应用到支持[]重载的类时都会有问题。
通过C++实现一种安全高效的数组大小运算符dimensionof(),以下是该运算符的实现:
template <int N> struct array_size_struct { byte_t c[N]; }; array_size_struct<N> static_array_size_fn(T (&)[N]); sizeof(static_array_size_fn(x).c) |
原理:声明一个模板函数static_array_size_fn(),它接受一个元素类型为T、大小为N的数组的引用,T和N分别作为它的两个模板参数,这样一来,指针以及用户自定义类型就拒之门外了,该函数返回array_size_struct类模板的一个实例,该类模板以static_array_size_fn()接受的数组大小来实参化,且内部包含一个对应大小的字节数组。dimensionof()宏则简单地将sizeof操作符应用到static_array_size_fn返回的实例中的数组成员身上,从而得到数组大小。
该dimensionof()总是在编译期被求值,因此dimensionof()可以被用在常量可以使用的任何地方。
C++标准中,sizeof的操作数不会被求值,所以无需产生
static_array_size_fn()函数体,从而该设施是零代价的,没有任何运行期开销,也不会代码膨胀。
测试代码如:
char cArray[40]; char *pCArray = cArray; vector<char> vecChar(50); size_t c_pCArray = NUM_ELEMENTS(pCArray); // 编译通过,执行异常 size_t c_vecChar = NUM_ELEMENTS(vecChar); // 编译通过,执行异常 c_pCArray = dimensionof(pCArray); // 编译不能通过 c_vecChar = dimensionof(vecChar); // 编译不能通过 |