5

Quando chiamo: a7 [0] [1] [100];Operatore [] Sovraccarico in array multidimensionali C++

Sono in grado di ottenere il primo indice '0' nell'operatore [] ma come indice non sarà in grado di ottenere altri valori di indice 1 e 100 in modo ricorsivo. Come potrei usare l'operatore [] per ottenere valori di indice folowing ricorsivi. In questo esempio per la matrice tridimensionale, l'operatore [] viene chiamato solo una volta per la prima dimensione che è '0'.

My Code Esempio:

template <class T, unsigned ... RestD> struct array; 

template <class T, unsigned PrimaryD> 
struct array <T, PrimaryD> { 
    typedef T type[PrimaryD]; 

    type data; 

    T& operator[] (unsigned i) { 
     return data[i]; 
    } 
}; 

template <class T, unsigned PrimaryD, unsigned ... RestD> 
struct array <T, PrimaryD, RestD...> { 
    typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 
    typedef OneDimensionDownArrayT type[PrimaryD]; 

    type data; 

    OneDimensionDownArrayT& operator[] (int i) { 
     OneDimensionDownArrayT& a = data[i]; 
     return a; 
    } 
}; 

int main() { 

    array<int, 1, 2, 3> a7 {{{{1, 2, 3},{4, 5, 6}}}}; 
    a7[0][1][2] = 100; //=>won't recursively go through operator[] 
        //I want to recursively obtain 0, 1 and 2 as index values 

    a7[0][1][100] = 100; //also works correctly. 
    std::cout << a7[0][1][100] << std::endl; 

    return 0; 
} 
+0

Quindi qual è il problema? Che comportamento stai vedendo? Se dà un errore di compilazione, che cos'è? Qual è il comportamento di runtime? Qual è il tuo compilatore e versione? Un po 'più di informazioni non fa male, lo sai! – yzt

+3

Hai considerato ... non farlo? Usa invece un overload 'operator()'. In realtà, le persone cercano * way * troppo difficile da calzare 'operatore []' in matrici multidimensionali. –

+5

Un paio di note a margine: [Perché l'interfaccia della mia classe Matrix non dovrebbe apparire come un array di array?] (Http://www.parashift.com/c++-faq/matrix-array-of-array.html) e [Ancora non capisco. Perché l'interfaccia della mia classe Matrix non dovrebbe apparire come un array di array?] (Http://www.parashift.com/c++-faq/matrix-c-style-subscript.html) –

risposta

1

L'errore qui è in realtà un po 'sottile, modificare la riga

typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 

a

typedef array<T, RestD...> OneDimensionDownArrayT; 

La ragione di questo è perché array<int, 1, 2, 3>::type eguali array<int, 2, 3>::type che equivale a array<int, 3>::type che è int. Alla fine si finisce con array<int, 1, 2, 3>::OneDimensionDownArrayT uguale a int[2][3]. Questo è il motivo per cui stavi scendendo di un livello solo nel tuo operatore sovraccarico [], perché restituisce una vera serie di interi. Si può vedere questo per te con l'aggiunta nel metodo principale:

 auto & e1 = a7[0]; 
     auto & e2 = e1[0]; 
     auto & e3 = e2[1]; 
     auto & e4 = e3[2]; 
     e4 = 100; 

invece di accedere tutti in una volta. Quindi sfoglia il debugger e controlla i tipi di e1-e4. e1 avrà tipo int (&) [2][3] anziché array<int, 2, 3> &.

Per allocarli nell'heap anziché nello stack, nella classe dichiarare i puntatori del proprio OneDimensionDownArrayT anziché degli array, definire i costruttori e un descrittore che si occuperà dell'allocazione/deallocazione degli array. Potrebbe sembrare qualcosa di simile:

template <class T, unsigned PrimaryD, unsigned ... RestD> 
    struct array <T, PrimaryD, RestD...> { 
     typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 

     array():data(new OneDimensionDownArrayT[PrimaryD]){} 
     ~array() { 
      delete[] data; 
     } 

     OneDimensionDownArrayT * data; 

     OneDimensionDownArrayT& operator[] (int i) { 
      OneDimensionDownArrayT& a = data[i]; 
      return a; 
     } 
    }; 

Si vuole anche definire un costruttore di copia, spostare costruttore e operatore di assegnazione per la classe. Questa implementazione richiederà molto meno spazio nello stack, ma nel complesso un po 'più di memoria in totale, poiché è necessario spazio per i puntatori e anche per gli array stessi.

+0

Questa soluzione è inefficiente per array molto grandi come a1 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]. Perché all'interno di ogni oggetto crea un altro oggetto array che quando la dimensione della dimensione aumenta l'utilizzo della memoria sarà così enorme. – Alper

+0

Non importa quello che fai, è necessario allocare spazio per 10! oggetti. Se si sta esaurendo lo spazio sullo stack, provare a utilizzare l'heap (allocando dinamicamente la memoria). – SirGuy

+0

typedef array OneDimensionDownArrayT; funziona ma sotto l'oggetto di ogni dimensione crea e mette in ordine l'oggetto e consumerà la memoria non ordinata. Ci sono più di 10 oggetti perché è un array multidimensionale. come potrei allocare dinamicamente => typedef array OneDimensionDownArrayT; – Alper

1

Se si desidera utilizzare in sequenza gli operatori [] e un array multidimensionale, ogni [] deve restituire un array (uno meno) -dimensionale.

Se il tipo di array multi-dimensionale è:

template <class Type, int dim> MArray; 

Poi un MArray<SomeType, n>::operator[] deve restituire un MArray<SomeType, n-1>. Con un caso speciale per l'array 1-D specifico che restituisce un oggetto (preferibilmente di riferimento) o un array 2-D che restituisce un array 1-D nativo. Questo esempio ha usato la notazione eccessivamente semplicistica, ma la chiave è che un n-D [] -operator restituisce un array (n-1) -D.