Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ STL: Can arrays be used transparently with STL functions?

Tags:

I was under the assumption that STL functions could be used only with STL data containers (like vector) until I saw this piece of code:

#include <functional> #include <iostream> #include <numeric> using namespace std;  int main() {     int a[] = {9, 8, 7};     cerr << "Sum: " << accumulate(&a[0], &a[3], 0, plus<int>()) << endl;     return 0; } 

It compiles and runs without any warnings or errors with g++, giving the correct output sum of 24.

Is such usage of arrays with STL functions allowed by the C++/STL standard? If yes, how do archaic structures like arrays fit into the grand STL plan of templated iterators, containers and functions? Also, are there any caveats or details in such usage that the programmer should be careful about?

like image 897
Ashwin Nanjappa Avatar asked Apr 03 '09 10:04

Ashwin Nanjappa


People also ask

Can C style arrays be used with STL algorithms?

The STL algorithms also provide support for c-style arrays. If you have c-style arrays with known size, you can directly use them together with the algorithms.

Are arrays part of STL?

A solution to using the primitive array is to use the array class that is part of the Standard Template Library (STL) and its set of containers.

How do you create an array in STL?

The general syntax of declaring an array container is: array<object_type, size> array_name; The above declaration creates an array container 'array_name' with size 'size' and with objects of type 'object_type'.

Are arrays part of STL C++?

Array data() in C++ STL with ExamplesC++ standard library contains many libraries that support the functioning of arrays. One of them is an array data() method. The array data() in c++ returns a pointer pointing to the first element of the object.


2 Answers

Well, you ask about an array. You can just easily get a pointer to its elements, so it basically boils down to the question whether pointers can be used transparently with STL functions. A pointer actually is the most powerful kind of an iterator. There are different kinds

  • Input iterator: Only forward and one-pass, and only read
  • Output iterator: Only forward and one-pass, and only write

  • Forward iterator: Only forward, and read/write
  • Bidirectional iterator: Forward and backward, and read/write
  • Random access iterator: Arbitrary steps forward and backward in one breath, and read/write

Now each iterator in the second group supports all the things of all iterators mentioned before it. A pointer models the last kind of iterators - a random access iterator. You may add/subtract an arbitrary integer and you may read and write. And all except the output iterator has a operator-> that can be used to access a member of the element type we iterate over.

Normally, iterators have several typedefs as members

  • value_type - what the iterator iterates over (int, bool, string, ...)
  • reference - reference to the value_type
  • pointer - pointer to the value_type
  • difference_type - what type the distance between two iterators has (returned by std::distance).
  • iterator_category - this is a tag-type: it is typedefed to a type that represents the kind of the iterator. either std::input_iterator_tag, ..., std::random_access_iterator_tag. Algorithms can use it to overload on different kinds of iterators (like std::distance is faster for random access iterators, because it can just return a - b)

Now, a pointer of course does not have those members. C++ has an iterator_traits template and specializes it for pointers. So if you want to get the value type of any iterator, you do

iterator_traits<T>::value_type 

And whether it is a pointer or some other iterator, it will give you the value_type of that iterator.

So - yes, a pointer can very well be used with STL algorithms. As someone else mentioned, even std::vector<T>::iterator can be a T*. A pointer is a very good example of an iterator even. Because it is so exceedingly simple but at the same time so powerful that it can iterate over a range.

like image 197
Johannes Schaub - litb Avatar answered Oct 15 '22 08:10

Johannes Schaub - litb


The standard has designed iterators to feel and behave as much like pointers as possible. Also, since iterators are based on templates, the only relevant thing is that the iterator type has the proper operators defined. The result is that pointers will out-of-the-box behave just like random access iterators.

In fact, a possible implementation of std::vector<T>::iterator is to just make it a T*.

Of course, for an array you won't have the useful begin() and end() methods to find the valid iterator range, but that's the problem you always have with C style arrays.

Edit: Actually, as has been mentioned in the comments and other answers, you can implement those functions for arrays if the array is not dynamic and has not decayed into a pointer. But my basic point was that you have to be more careful than when using the standard containers.

like image 34
CAdaker Avatar answered Oct 15 '22 07:10

CAdaker