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<std::unique_ptr<someClass>>> myArray;

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


2 个解决方案



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.

一般來說,就像任何過於復雜的問題一樣,嘗試將其分解。用於在C和C ++中分解復雜類型聲明的工具長期以來一直是“typedef”。下面是如何處理類似於您所擁有的級聯類型定義:采用最里面的包裝類型,即包裝類的unique_ptr,並為要包裝的類型創建一個typedef。然后,繼續對該類型包裝的類型執行相同操作,直到您處於最外層類型。

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: Go check out that link if that is of interest to you in this context or becomes relevant in the future!

這與您的問題僅相關,但我想提及它,因為您可能會遇到類似於您現在使用模板的類似問題。從C ++ 11開始,您可以更方便地使用“using”子句為涉及模板參數的類型定義別名:。如果在這種情況下您感興趣或在將來變得相關,請查看該鏈接!

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 {
    ~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: 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.




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().

作為一個說明性示例,下面是可以在C ++現代中使用的語法,用於使用智能指針(unique_ptr)和其他功能(如make_unique和move())創建和填充2D int數組(大小為3 x 5)。

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;
    smartPtr2D[i] = move(smartPtr1D);



粤ICP备14056181号  © 2014-2020