5

スマートポインタの2次元配列を動的に割り当てる必要がありますが、その構文がわかりにくいです。私は、これは動的にする必要があります。スマートポインタの2D配列を動的に割り当てるための構文

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

だから私は、私は型へのポインタへのポインタを作成して理解して何から:

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

そして、それを割り当てるために、私はない:

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

しかしこれはスマートポインタを使用しないので、後で手動で削除する必要があり、これらのポインタをスマートポインタにする方法がわかりません。

タイプがのstd :: unique_ptrをですが、その後、私は型へのポインタへのポインタを必要とするので、私は試してみました:

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

しかし、この後、私はそれを割り当てるだろうかに迷ってしまいました。誰かが私を助けてくれますか?

+4

1D 'vector >は、スマートポインタの2D配列に適しています。 – juanchopanza

+1

また、2次元配列はダブルポインタではありません。 –

+2

C++では、 "Xの2次元配列"は 'std :: vector >'と綴られています。 –

答えて

3

あなたの問題を具体的に解決する方法と、このような一般的な問題にどのようにアプローチするかを説明します。

一般的に、複雑すぎる問題と同様に、それを分解しようとします。 CおよびC++で複合型宣言を分解するツールは、以前から「typedef」でした。あなたが持っているもののようなカスケード型定義のためにアプローチする方法は次のとおりです。最も内側のラッピング・タイプ、つまりクラスをラップするunique_ptrを取り、ラップするタイプのtypedefを作成します。次に、あなたが最も外側のタイプになるまで、そのタイプがラップしているタイプについて同じことを続行します。

これはあなたの質問にのみ関連していますが、後でテンプレートを使用しているような同様の問題に遭遇する可能性があるため、言及したいと思います。 C++ 11以降、 "using"句を使用してテンプレートパラメータを含む型のエイリアスをより便利に定義することができます。http://en.cppreference.com/w/cpp/language/type_alias。この文脈で興味のあるものであれば、そのリンクをチェックしてください。

あなたの特定の問題。関数 "test_dynamic_2darray1"は、スマートポインタの2次元10x10配列を構築します。このコードを実行すると、管理対象配列が有効範囲外になったときに、デストラクタから100行の出力が表示されます。

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]; 
} 

私は私はあなたの質問に答えることができたと思っている:

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]); 
} 

は動的に割り当てられたクラスのインスタンスのデストラクタが呼び出されません、あなたは何も出力を見ていない、このコードにすることを比較します! :)あなたが私に何かを詳しく説明してもらいたいかどうか私に教えてください!先日あなたに興味のあるかもしれない関連ブログ記事を書きました:http://frankriesecodingblog.blogspot.com/2015/01/performance-of-dynamic-multi.html。多次元動的配列に対するさまざまなアプローチを示し、頻繁に提案されたベクトルのベクトルを使用する方法のパフォーマンスを調べるので、私はここにそれを掲示しています。

最後に、intを使って配列を繰り返し処理する方法について説明します。私はこれが私のペットピーブに変わっていないことを願っていますが、私はこれがたくさん行われているのを見ています。あなたはおそらくsize_tを使うべきです。どうして?例えば、私の64ビットマシンでは、 "int"は32ビットですが、size_tで表されるアドレスは64ビットです。このintの誤用は、特に32ビットアプリケーションを64ビットマシンに移植する多くのバグの原因となっています。配列型のアドレス間のオフセットなどの用途のために、符号付きの型が必要な場合は、おそらくptrdiff_tを使用する方がよいでしょう。

+0

私の問題にあなたの解決策を適用しようとしましたが、処理のために関数の2次元配列を2次元配列に渡そうとすると、次のエラーが発生します: 'error C2664: 'functionName': 'std :: unique_ptr <_Ty> * 'to' double ** ''。基本的には、私は2Dの二重配列を作成し、メモリを割り当てたい、いくつかの初期化コードがあり、それは関数に渡されます。関数が例外をスローする場合は、スマートポインタを使用して後でクリアするのに役立ちます。 – Ben

+0

私は、 'dimension2'(あなたの例では)をダムポインタとして設定しますが、スマートポインタを使って初期化し、.get()を使って2D配列に割り当てていると思いますか? – Ben

2

例示的な例としては、以下スマートポインタ(unique_ptr)などmake_uniquemove()などの他の機能を使用して(5によるサイズ3の)2次元int配列を作成し、充填するためにC++近代的に使用することができる構文です。

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); 
} 
関連する問題