Gar
Gar

Reputation: 305

Accessing a std::array via a unique_ptr

This is just for learning purposes, I know I can just use a vector but I have

const int N = 1e3;
auto my_arr = std::make_unique<std::array<int, N>>();

// To access it I have to do this - why [0][0] twice?
my_arr.get()[0][0] = 1;

// Getting the size for fun
std::cout << sizeof(my_arr.get()) << "\n"; // outputs 8
std::cout << sizeof(my_arr.get()[0]) << "\n"; // outputs 800000000
std::cout << sizeof(my_arr.get()[0][0]) << "\n"; // outputs 8

I understand that .get() returns a pointer to the managed object but I don't understand why I need to do my_arr.get()[0][0] twice?

Upvotes: 1

Views: 1361

Answers (4)

t.niese
t.niese

Reputation: 40842

As you said yourself .get() returns a pointer to the managed object.

So it is std::array<int, N>* what you return and not std::array<int, N>:

std::array<int, N>* array_ptr = my_arr.get();

So either write (*my_arr)[0] or (*my_arr.get())[0]

Upvotes: 3

Barry
Barry

Reputation: 303087

You probably don't want to do this:

auto my_arr = std::make_unique<std::array<int, N>>();

Unless you really specifically want an array<int, N>. If what you just want to do is dynamically allocate N ints and manage that with a unique_ptr, that's:

auto my_arr = std::make_unique<int[]>(N);

The advantages here are:

  • N can be a runtime value, it doesn't have to be a constant-expression.
  • unique_ptr<T[]>::operator[] exists and does what you want, so my_arr[2] does index into the array.

Upvotes: 4

Peter Ruderman
Peter Ruderman

Reputation: 12485

Well, you don't have to do that, but it works.

my_arr.get() returns a std::array<int,N>*

Like any pointer, you can index it like an array.

my_arr.get()[0] returns a reference to the first element in your 'array' of arrays.

You can then use std::array's indexing operator to get an element.

my_arr.get()[0][0] returns a reference to the element you want.

Alternatively, you could write:

my_arr->at(0)
my_arr->operator[](0)
(*my_arr)[0]
*my_arr->data()

Upvotes: 5

NathanOliver
NathanOliver

Reputation: 180630

my_arr.get() gives you a std::array<int, N>*. Since you have a pointer doing pointer[0] is the same as *pointer. So you don't actually need my_arr.get()[0][0] and you can instead use

(*my_arr.get())[0]

to show that you are dereferencing the pointer. In fact, you could just use

(*my_arr)[0]

because operator * is overloaded for std::unique_ptr and it will return a reference to the pointed to thing.

Upvotes: 7

Related Questions