問題を具体的に解決する方法と、このような問題に一般的にアプローチする方法を紹介します。
一般に、複雑になりすぎる問題と同じように、それを分解してみてください。C および C++ で複雑な型宣言を分解するためのツールは、長い間 "typedef" でした。あなたが持っているもののようなカスケード型定義にアプローチする方法は次のとおりです。最も内側のラッピングタイプ、つまりクラスをラッピングするunique_ptrを取り、ラップしたいタイプのtypedefを作成します。次に、最も外側の型になるまで、その型がラップされている型に対して同じことを続けます。
これはあなたの質問にのみ関連していますが、後でテンプレートで現在抱えているような同様の問題に遭遇する可能性があるため、言及したいと思います。C++11 以降、"using" 句を使用して、テンプレート パラメーターを含む型のエイリアスをより便利に定義することもできます: http://en.cppreference.com/w/cpp/language/type_alias。このコンテキストで興味がある場合、または将来的に関連する場合は、そのリンクをチェックしてください!
あなたの特定の問題に。関数 "test_dynamic_2darray1" は、スマート ポインターの 2 次元 10x10 配列を構築します。このコードを実行すると、マネージ配列が範囲外になったときに、デストラクタから 100 行の出力が表示されます。
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]);
}
動的に割り当てられたクラス インスタンスのデストラクタが呼び出されず、出力が表示されないこのコードと比較してください。
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];
}
私はあなたの質問に答えることができたことを願っています! :) 何か詳しく説明してほしい場合はお知らせください。先日、関連するブログ投稿も書きました。多次元動的配列へのさまざまなアプローチを示し、ベクトルのベクトルを使用する頻繁に提案される方法のパフォーマンスを調べるため、ここに投稿します。
最後になりましたが、配列を反復処理するための int の使用について言及させてください。これが私の面倒なことにならないことを願っていますが、これがたくさん行われているのを見ています. おそらくsize_tを使用する必要があります。なんで?たとえば、私の 64 ビット マシンでは "int" は 32 ビットですが、size_t で表されるアドレスは 64 ビットです。この int の誤用は、特に 32 ビット アプリケーションを 64 ビット マシンに移植する際に、多くのバグの原因となっています。配列アドレス間のオフセットなどの用途で符号付き型が必要な場合は、おそらく ptrdiff_t を使用することをお勧めします。