Ti mostrerò come risolvere il tuo problema in modo specifico e come affrontare problemi come questo in generale.
In generale, proprio come qualsiasi problema che diventa troppo complesso, provare a scomposizione. Lo strumento per scomporre le dichiarazioni di tipo complesso in C e C++ è stato a lungo il "typedef". Ecco come ci si avvicina per le definizioni di tipi in cascata come quella che si sta facendo: prendi il tipo di wrapping più interno, cioè il unique_ptr che avvolge la tua classe e crea un typedef per il tipo che vuoi avvolgere. Quindi, continua a fare lo stesso per il tipo che quel tipo sta eseguendo il wrapping, finché non sei al tipo più esterno.
Questo è tangenzialmente correlato alla tua domanda, ma voglio menzionarlo, perché potresti imbatterti in un problema simile a quello che stai avendo ora con i modelli successivi. Dal momento che in C++ 11 è possibile definire più facilmente anche alias per tipi che coinvolgono parametri di template con la clausola "using": http://en.cppreference.com/w/cpp/language/type_alias. Vai a controllare quel link se ti interessa in questo contesto o diventa rilevante in futuro!
Per il vostro problema specifico. La funzione "test_dynamic_2darray1" crea un array bidimensionale 10x10 di puntatori intelligenti. Quando si esegue questo codice, è necessario visualizzare 100 righe dell'output dal distruttore, solo quando l'array gestito non rientra nell'ambito.
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]);
}
Confronti che, per questo codice, qualora non vengano chiamati i distruttori delle istanze di classe allocati dinamicamente e si vede alcun 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];
}
Spero di essere stato in grado di rispondere alla tua domanda! :) Fammi sapere se vuoi che elabori qualcosa! Ho anche scritto un post sul blog correlato l'altro giorno che potrebbe interessarti: http://frankriesecodingblog.blogspot.com/2015/01/performance-of-dynamic-multi.html. Lo sto postando qui, perché mostra diversi approcci ad array dinamici multidimensionali e esamina le prestazioni del metodo spesso suggerito di utilizzare vettori di vettori.
Ultimo ma non meno importante, lasciatemi menzionare l'utilizzo di int per iterare su array. Spero che questo non si trasformi in un mio vero problema, ma vedo che questo è stato fatto molto. Probabilmente dovresti usare size_t. Perché? Ad esempio, sulla mia macchina a 64 bit "int" è a 32 bit, ma gli indirizzi, rappresentati da size_t, sono a 64 bit. Questo uso improprio di int è stato la causa di molti bug, in particolare per il porting di applicazioni a 32 bit su macchine a 64 bit.Se hai bisogno di un tipo firmato, per usi come offset tra gli indirizzi di array, un uso migliore sarebbe probabilmente ptrdiff_t.
Un 1D 'vettore>' dovrebbe essere un buon sostituto per una matrice 2D di puntatori intelligenti. –
juanchopanza
Inoltre, gli array bidimensionali non sono doppi puntatori. –
In C++, "array bidimensionale di X" è scritto 'std :: vector>'. –