2
votes

I am trying to declare and initialize a unique_ptr holding a class array

This is a sample I am using to solve a memory management issue with my project. I can declare the pointer but I am not able to initialize it.

class CrewMember
{   
};


class SpaceShip
{

// generates error
std::unique_ptr<CrewMember[3][3]> ship_crew_members = std::make_unique< new CrewMember[3][3]>; 

// compiles fine
std::unique_ptr<CrewMember[3][3]> ship_crew_members;

};

errors received:

call to non-constexpr function 'void* operator new ' std::unique_ptr ship_crew_members = std::make_unique< new CrewMember[3][3]>;
^
cannot resolve overloaded function 'make_unique' based on conversion to type 'std::unique_ptr' std::unique_ptr ship_crew_members = std::make_unique< new CrewMember[3][3]>;

1
make_unique is a function template. You need to do make_unique<Type>().L. F.
std::make_unique< new CrewMember[3][3]> 90% sure you can't use new in this context.user10957435
Also, it should be something more along the lines of std::make_unique<CrewMember[3][3]>(), though I'm not sure this is completely correct.user10957435
@L.F. and Chipster I will give that a shot. Thank you for the quick response!Manual
Tried this: cpp std::unique_ptr<CrewMember[3][3]> ship_crew_members = std::make_unique< CrewMember[3][3]>(); recieved pastebin.com/Kma1Q4S8Manual

1 Answers

1
votes
  1. std::unique_ptr stores a pointer to either a single object, or to a one-dimensional array. Multi-dimensional arrays are not supported. It can theoretically store a pointer to a multidimensional array, if you do an evil cast, but you really should not.

  2. If you really want to use std::unique_ptr to store a multidimensional array, you'd need to do some extra work and use a one-dimensional array and then calculate the offset for the multidimensional index yourself (e.g. [1][2] becomes 1*3+2).

  3. std::make_unique is a function template. The template parameter needs to be a proper type, which either is a class or a class array (but without the size). If your type is an array and you give std::make_unique a size as parameter, it will create a std::shared_ptr that points to an array of that size and uses the proper delete[] operator on that array when it gets destructed.

All together that would look something like so:

std::shared_ptr<CrewMember[]> ship_crew_members = std::make_shared<CrewMember[]>(9);

However I strongly advice against doing this. Much simpler is to use any of the std containers, e.g. std::vector:

std::vector<std::vector<CrewMember>> ship_crew_members;

This gives you a multidimensional container of varying size, that you can add elements to or remove elements from.

Or std::array for a fixed size multidimensional array:

std::array<std::array<CrewMember, 3>, 3> ship_crew_members;