(assuming that I can not use STL container)
#include <iostream>
int main()
{
wchar_t my_array[] = { L'h', L'e', L'l', L'l', L'o' };
for (const auto& wch : my_array) {
std::wcout << wch;
}
}
The range-based for loop in C++ uses the begin()
and end()
functions to determine the range of elements to iterate over. In the case of an array, as above, std::begin(my_array)
returns a pointer to the first element of the array, and std::end(my_array)
returns a pointer to one past the last element of the array.
It works, but is it UB?
No. It is not undefined.
A pointer can point one past the last element of an array.
Actually std::vector
iterators can be implemented as raw pointers. Also a pointer to an object can be regarded as pointer to a single element array. Incrementing such pointer once is legal. You just may not dereference it. The end
pointer / iterator is not dereferenced in the ranged based for loop. Dereferencing the end
iterator would be UB as well as dereferencing the pointer.
int a[] = {1,2,3};
int* a_end = a + 3; // OK
// *a_end ... NOT OK
int x = 42;
int p = &x;
int* p_one_past = p+1; // not that useful, but OK
// *p_one_past ... NOT OK
Also when using c-style arrays with algorithms that expect first
and last
iterators it is common to pass a one-past-last-element pointer:
int a[] = {3,2,1};
std::sort( std::begin(a) , std::end(a) );
Here std::end(a)
is the same as a + std::size(a)
is the same as a + 3
.