Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply std::begin() on an dynamically allocated array in a unique_ptr?

Tags:

c++

c++11

I have an unique pointer on a dynamically allocated array like this:

const int quantity = 6;
unique_ptr<int[]> numbers(new int[quantity]);

This should be correct so far (I think, the [] in the template parameter is important, right?). By the way: Is it possible to initialize the elements like in int some_array[quantity] = {}; here?

Now I was trying to iterate over the array like this:

for (auto it = begin(numbers); it != end(numbers); ++it)
    cout << *it << endl;

But I cannot figure out, how the syntax is right. Is there a way? Alternatively I can use the index like:

for (int i = 0; i < quantity; ++i)
    cout << numbers[i] << endl; 

Is one of these to be preferred?

(Not directly related to the title: As a next step I would like to reduce that to a range-based for loop but I just have VS2010 right now and cannot try that. But would there be something I have to take care of?)

Thank you! Gerrit

like image 764
Gerrit Avatar asked Apr 13 '13 20:04

Gerrit


2 Answers

Compiler is supposed to apply this prototype for std::begin:

template< class T, size_t N > 
T* begin( T (&array)[N] );

It means the parameter type is int(&)[N], neither std::unique_ptr nor int *. If this is possible, how could std::end to calculate the last one?

But why not use raw pointer directly or a STL container?

const int quantity = 6;
std::unique_ptr<int[]> numbers{new int[quantity]};
// assignment
std::copy_n(numbers.get(), quantity,
            std::ostream_iterator<int>(std::cout, "\n"));

const int quantity = 6;
std::vector<int> numbers(quantity, 0);
// assignment
std::copy(cbegin(numbers), cend(numbers),
          std::ostream_iterator<int>(std::cout, "\n"));
like image 128
Matt Yang Avatar answered Sep 27 '22 23:09

Matt Yang


Dynamically allocated arrays in C++ (ie: the result of new []) do not have sizing information. Therefore, you can't get the size of the array.

You could implement std::begin like this:

namespace std
{
  template<typename T> T* begin(const std::unique_ptr<T[]> ptr) {return ptr.get();}
}

But there's no way to implement end.

Have you considered using std::vector? With move support, it shouldn't be any more expensive than a unique_ptr to an array.

like image 43
Nicol Bolas Avatar answered Sep 28 '22 01:09

Nicol Bolas