How does the range-based for work for plain arrays? How does the range-based for work for plain arrays? arrays arrays

How does the range-based for work for plain arrays?


It works for any expression whose type is an array. For example:

int (*arraypointer)[4] = new int[1][4]{{1, 2, 3, 4}};for(int &n : *arraypointer)  n *= 2;delete [] arraypointer;

For a more detailed explanation, if the type of the expression passed to the right of : is an array type, then the loop iterates from ptr to ptr + size (ptr pointing to the first element of the array, size being the element count of the array).

This is in contrast to user defined types, which work by looking up begin and end as members if you pass a class object or (if there is no members called that way) non-member functions. Those functions will yield the begin and end iterators (pointing to directly after the last element and the begin of the sequence respectively).

This question clears up why that difference exists.


I think that the most important part of this question is, how C++ knows what the size of an array is (at least I wanted to know it when I found this question).

C++ knows the size of an array, because it's a part of the array's definition - it's the type of the variable. A compiler has to know the type.

Since C++11 std::extent can be used to obtain the size of an array:

int size1{ std::extent< char[5] >::value };std::cout << "Array size: " << size1 << std::endl;

Of course, this doesn't make much sense, because you have to explicitly provide the size in the first line, which you then obtain in the second line. But you can also use decltype and then it gets more interesting:

char v[] { 'A', 'B', 'C', 'D' };int size2{ std::extent< decltype(v) >::value };std::cout << "Array size: " << size2 << std::endl;


According to the latest C++ Working Draft (n3376) the ranged for statement is equivalent to the following:

{    auto && __range = range-init;    for (auto __begin = begin-expr,              __end = end-expr;            __begin != __end;            ++__begin) {        for-range-declaration = *__begin;        statement    }}

So it knows how to stop the same way a regular for loop using iterators does.

I think you may be looking for something like the following to provide a way to use the above syntax with arrays which consist of only a pointer and size (dynamic arrays):

template <typename T>class Range{public:    Range(T* collection, size_t size) :        mCollection(collection), mSize(size)    {    }    T* begin() { return &mCollection[0]; }    T* end () { return &mCollection[mSize]; }private:    T* mCollection;    size_t mSize;};

This class template can then be used to create a range, over which you can iterate using the new ranged for syntax. I am using this to run through all animation objects in a scene which is imported using a library that only returns a pointer to an array and a size as separate values.

for ( auto pAnimation : Range<aiAnimation*>(pScene->mAnimations, pScene->mNumAnimations) ){    // Do something with each pAnimation instance here}

This syntax is, in my opinion, much clearer than what you would get using std::for_each or a plain for loop.