Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntax for dynamically allocating a 2D array of smart pointers

I need to dynamically allocate a two dimensional array of smart pointers but the syntax for it is confusing me. I need this to be dynamic:

std::unique_ptr<someClass> myArray[size1][size2];

So from what I understand I create a pointer to a pointer to the type:

someClass** myArray; //actaully the type is std::unique_ptr<someClass> but I'll just keep it simple

Then to allocate it I do:

myArray* = new someClass*[size1];
for(int i = 0; i < size1; i++)
    myArray[i] = new someClass[size2];

But this doesn't use smart pointers which means I will have to manually delete it later, and I don't know how to make these pointers smart pointers;

The type is std::unique_ptr but then I need a pointer to a pointer to the type, so I tried:

std::unique_ptr<std::unique_ptr<std::unique_ptr<someClass>>> myArray;

But after this I'm lost on how I would allocate it. Could someone please help me out?

like image 773
ProgrammerGuy123 Avatar asked Mar 18 '13 22:03

ProgrammerGuy123


People also ask

How to allocate memory for a 2D array of pointers?

Using Single Pointer In this approach, we simply allocate memory of size M × N dynamically and assign it to the pointer. Even though the memory is linearly allocated, we can use pointer arithmetic to index the 2D array. 2. Using Array of Pointers

How to dynamically allocate a 2D array in C?

How to dynamically allocate a 2D array in C? Following are different ways to create a 2D array on heap (or dynamically allocate a 2D array). A simple way is to allocate memory block of size r*c and access elements using simple pointer arithmetic.

What is dynamic memory allocation in C++?

Hello, Coders! In this C++ tutorial, we will learn about dynamic memory allocation, as well as initialize a 2D array in C++ using the pointers and new operator. It is the process of allocating the memory at run time within the heap. In this process, the memory allocation is performed manually by the programmer.

How to create an array of pointers dynamically in C language?

ptr [i] = i + 1; //Giving value to the pointer and simultaneously printing it. We can create an array of pointers of size r. Note that from C99, C language allows variable sized arrays. After creating an array of pointers, we can dynamically allocate memory for every row. We can create an array of pointers also dynamically using a double pointer.


2 Answers

I'll show you how to solve your problem specifically and how to approach problems like this one in general.

In general, just like any problem that gets too complex, try to break it down. The tool for breaking down complex type declarations in C and C++ has long been the "typedef". Here is how you approach it for cascaded type definitions like the one you are having: take the innermost wrapping type, i.e. the unique_ptr wrapping your class, and make a typedef for the type you want to wrap. Then, proceed doing the same for the type which that type is wrapping, until you are at the outermost type.

This is tangentially related to your question only, but I want to mention it, because you might run into a similar issue like the one you are having now with templates later. Since C++11 you can more conveniently also define aliases for types involving template parameters with the "using" clause: http://en.cppreference.com/w/cpp/language/type_alias. Go check out that link if that is of interest to you in this context or becomes relevant in the future!

To your specific problem. The function "test_dynamic_2darray1" builds a two-dimensional 10x10 array of smart pointers. When you run this code, you should see 100 lines of the output from the destructor, just when the managed array goes out of scope.

size_t destructor_count = 0;
class MyClass {
    public:
    ~MyClass() {
        std::cout << "Destructor call #" << ++destructor_count << std::endl;
    }
};

typedef std::unique_ptr<MyClass[]> ManagedC;

void test_dynamic_2darray1() {
    size_t dimension1 = 10, dimension2 = 10;

    auto managed_array = std::unique_ptr<ManagedC[]>(new ManagedC[dimension1]);
    for (size_t i = 0; i < dimension1; ++i)
        managed_array[i] = ManagedC(new MyClass[dimension2]);
}

Compare that to this code, where the destructors of the dynamically allocated class instances will not be called and you see no output:

void test_dynamic_2darray2() {
    size_t dimension1 = 10, dimension2 = 10;

    auto simple_array = new MyClass*[dimension1];
    for (size_t i = 0; i < dimension1; ++i)
        simple_array[i] = new MyClass[dimension2];
}

I hope I have been able to answer your question! :) Let me know if you want me to elaborate on something! I also wrote a related blog post the other day that may interest you: http://frankriesecodingblog.blogspot.com/2015/01/performance-of-dynamic-multi.html. I am posting it here, because it shows different approaches to multi-dimensional dynamic arrays and looks into the performance of the often suggested method of using vectors of vectors.

Last but not least, let me mention your use of int to iterate over arrays. I hope this isn't turning into a pet peeve of mine, but I see this being done a lot. You should probably use size_t. Why? For example, on my 64 bit machine "int" is 32 bit, but addresses, represented by size_t, are 64 bit. This misuse of int has been the cause of many bugs, in particular for porting 32 bit applications to 64 bit machines. If you need a signed type, for uses such as offsets between array addresses, a better use would probably be ptrdiff_t.

like image 91
user2880576 Avatar answered Sep 29 '22 06:09

user2880576


As an illustrative example, below is the syntax that can be used in C++ modern for creating and filling a 2D int array (of size 3 by 5) using smart pointer (unique_ptr) and other features such as make_uniqueand move().

unique_ptr<unique_ptr<int[]>[]>     smartPtr2D;
unique_ptr<int[]>                   smartPtr1D;

int dataCounter = 0;

smartPtr2D = make_unique< unique_ptr<int[]>[] >(3);
for (int i = 0; i<3; i++)
{
    smartPtr1D = make_unique<int[]>(5);
    for (int j = 0; j<5; j++)
    {
        smartPtr1D[j] = dataCounter;
        dataCounter++;
    }
    smartPtr2D[i] = move(smartPtr1D);
}
like image 36
A Prec Avatar answered Sep 29 '22 08:09

A Prec