2012-11-13 50 views
9

当我做这样的事情:C++ 11基于范围的for循环如何知道数组大小?

int my_array[5] = {1, 2, 3, 4, 5}; 
for (int &x : my_array) { 
    x *= 2; 
} 

C++ 11显然知道,我的数组只有5个元素。这些信息是否存储在my_array对象的某个地方?

如果是这样,是否有充分的理由说明为什么它不能作为开发人员使用(或者它是?!?!?)?看来,如果C++开发人员总是知道他们正在处理的数组的范围,那么世界上的许多问题都将得到解决。

回答

11

这只是语言需要工作的东西,编译器必须实现。很明显,my_array的完整类型是int[5](即尺寸是类型的一部分),所以这个信息是容易获得的。

流行的看法相反,有没有使用在游戏中自由std::begin()/std::end()功能,虽然这些会天真地似乎是能够做的伎俩(但有涉及ADL一抓,将打破这种做法) 。

+0

确定。那么为什么my_array.size不存在有什么特别的原因? – MrFox

+6

@suslik:当然,因为数组不是类的类型,因此不能有成员函数。但是你可以简单地编写一个产生所需值的'array_size'自由函数模板,或者使用容易制作的['std :: extent'](http://en.cppreference.com/w/cpp/types/extent )。 –

+0

我是如何过这么久才知道这么久的......我怪std :: vector :)。 – MrFox

5

不,它不是对象的一部分。但它是这种类型的一部分。这就是数组声明中的5。然而,这是不行的:

void f(int arr[5]) { 
    for(int& x: arr) { 
     // whatever 
    } 
} 

因为数组的名字在这里衰变成一个指针,它的第一个元素,即,参数声明等效于int *arr不具有大小信息。

+3

在这种情况下,我不会使用术语“衰变”。我认为该术语通常特定于在许多表达式中对数组变量所做的隐式转换。 'int a [5]; a + 1; // decay'相反,我喜欢用“调整”一词来表示这里发生的事情,因为这是标准使用的词。 void foo(int a [5]); //输入'adjustment':相当于void foo(int * a)'。我说这个词时,我喜欢用讽刺的语调。 – bames53

+0

虽然这会工作。 'void f(int(&arr)[5]){...}' – balki

+0

作为参考,@ balki的解决方案不适用于未定义的数组引用。 '(ARR)[5]'。但通常可以通过使用数组大小​​作为模板参数来处理泛型大小的数组:请参阅https://stackoverflow.com/questions/26182907/range-based-for-loop-on-array-passed-非主要功能 – andybuckley

6

它可用 - 您可以在标准C++的数组上定义beginend。数组的大小以类型编码。

一般的方法是使用对数组的引用。

下面是一个例子大小功能:

template<typename T, size_t N> 
size_t array_size(T (& const)[N]) 
{ 
    return N; 
} 
+6

这也被称为'std :: extent'。已经为标准库中的数组定义了“std :: begin”和“std :: end”。 –

相关问题