Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using iterators on arrays

It is stated in C++ Primer that

In C++ pointers and arrays are closely intertwined. In particular, as we’ll see, when we use an array, the compiler ordinarily converts the array to a pointer.

I wanted to use iterators for printing an array. The program below works fine but when I try to print arr2 or arr3, if I'm not mistaken, which is of type int *, I get an error (judging that the & operator means reference below).

error: no matching function for call to ‘begin(int*&)’

int main(int argc, char** argv) {

    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    auto arr2 = arr;
    auto arr3(arr);   // I think arr2 and arr3 are of same type

    for(auto it = std::begin(arr) ; it != std::end(arr) ; ++it)
        std::cout << *it << " ";
    std::cout << std::endl;

    return 0;
}

Considering the statement, if an array is converted into a pointer by the compiler, how does this program work for printing contents of arr using std::begin() and std::end() and do not work for arr2 or arr3 if all of them are pointers to integers?


Edit

I'm sorry if I couldn't make it clear. I hope I'll clarify the problem by this edit.

Now that I am aware that begin() and end() won't work with pointers (thanks to the answers), I wonder if the quoted text is not true as it specifies that there is an Array -> Pointer conversion. If what text says is true then the type of arr should be a pointer. Is there a problem with the quoted text at this point?

Also, is there any way that I can use begin() and end() for pointers (not STL containers) with specifying the size, possibly using the following constructor?

template< class T, size_t N > 
T* begin( T (&array)[N] );
like image 1000
Varaquilex Avatar asked May 08 '14 13:05

Varaquilex


2 Answers

An array is converted to a pointer easily, but not always. For example, if you take the address of the array or get a reference then the original array type isn't lost:

int a[10];
int (&ar)[10] = a; // fine
int (*ap)[10] = &a; // also fine

However, when you use an array in a way where most other types would be copied, the array is converted to a pointer and the pointer is copied instead.

In your example, you can use arr2 if you make it be a reference:

 auto &arr2 = arr;

Now arr2 has type int (&)[10] instead of int *.

like image 65
Vaughn Cato Avatar answered Sep 28 '22 06:09

Vaughn Cato


Because std::begin is defined for arrays but not for pointers. An array type is not the same as a pointer type.

The problem here is that apparently the auto arr2 = arr degrades the type from the array type to a pointer type.

Note that the problem is actually in std::end not in std::begin. After all how would std::end be able to give the pointer to the last+1 element when all it has is a pointer to the first element? It can't, therefore std::end cannot be defined for a pointer type and hence std::begin does not make any sense for a pointer type.

To be precise the type of arr is int[10] while that of arr2 and arr3 is int*. The former can degrade into the latter but not vice versa.

like image 40
wich Avatar answered Sep 28 '22 04:09

wich