如何获取c++ Array元素个数

原文地址:https://blogs.msdn.microsoft.com/the1/2004/05/07/how-would-you-get-the-count-of-an-array-in-c-2/

这个问题可简单描述为:
给定一个c++ 数组(如:int x[10]),如何获取它的元素个数?

一种显而易见的方法是使用宏(定义1):

#define countof( array ) (sizeof( array )/sizeof( array[0] ))

我不能说这种方法不正确,因为在给定一个数组,他确实能获取其元素个数。然而,当提供的对象不是数组时,同样的表达式会给你一些不真实的结果。例如,如果你提供

int* p;

这时当运行在int指针和int拥有相同大小(如win32平台)机器上,countof( p )总是返回1。

这种宏表示也可以错误接受任何有operator[]方法的类对象。例如,假设你写的代码如下:

class IntArray {
 private:
  int* p;
  size_t size;

 public:
  int &operator[](size_t i);
} x;

此时,sizeof(x)将返回x对象的大小,而不是x.p指向buffer的大小。因此,通过countof(x),你将不能获取正确值。

所以我们可以断言定义1不是一种好的方法,因为编译器不能阻止你错用它。它不能强制只传递数组。

有没有更好的选择呢?

是的,如果我们希望编译器保证coutof的参数总是数组,我们必须找到一个只允许数组的上下文,且同时必须拒绝所有非数组的表达式。

一些初学者可能尝试这样(定义2):

template <typename T, size_t N>

size_t countof(T array[N])
{
  return N;
}

他们认为,这个模板函数将接受大小为N的数组,并返回N。

不幸的是,这将编译不过,因为C++对待数组形参等同于指针参数,也就是上述的定义等同于:

template <typename T, size_t N>
size_t countof(T* array)
{
  return N;
}

现在显然函数主体没方法知道N是多少。

然而,如果传入的参数是数组引用,此时编译器保证实参的大小匹配形参。这意味我们小改定义2,使其工作(定义3):

template <typename T, size_t N>
size_t countof(T (&array)[N])
{
  return N;
}

这个countof能工作很好,且你不能传递指针参数。但是,它是个函数,而不是宏。这意味着你不能用它作为编译常数。尤其,你不能写代码如下:

int x[10];

int y[2*countof(x)];

我们还有其他方法吗?

有人(我不知道具体是谁)提出更好的主意:
从函数主体移出N至返回类型,此时我们能获取N,而不需要实际调用函数。

确切地说,我们必须让函数返回一个数组引用,因为C ++不允许直接返回数组。

具体实现:

template <typename T, size_t N>

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

正如我们希望的,变为有效定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值