2016-04-08 23 views
6

Ho un array 2D creato dinamicamente.Come usare memset o fill_n per inizializzare una matrice bidimensionale dinamica in C++

int **abc = new int*[rows]; 

for (uint32_t i = 0; i < rows; i++) 
{ 
    abc[i] = new int[cols]; 
} 

Voglio riempire l'array con qualche valore (ad esempio 1). Posso scorrere su ogni oggetto e farlo.

Ma c'è un modo più semplice. Sto cercando di utilizzare memset e std::fill_n come indicato in this post.

std::fill_n(abc, rows * cols, 1); 
memset(abc, 1, rows * cols * sizeof(int)); 

L'utilizzo di memset causa il blocco del programma. L'uso di fill_n dà un errore di compilazione.

invalid conversion from 'int' to 'int*' [-fpermissive] 

Cosa sto facendo di sbagliato qui?

+0

Dropping torna a C potrebbe essere un'opzione: 'int (* abc) [cols] = malloc (rows * sizeof (* abc)); memset (abc, 1, rows * sizeof (* abc)); 'è legale C dal C99, ma non sarà possibile in C++ in qualunque momento presto. – cmaster

risposta

5

Si potrebbe utilizzare vector:

std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1)); 

Non è possibile utilizzare std::fill_n o memset su abc direttamente, semplicemente non funzionerà. È possibile utilizzare solo sia sui sub-array:

int **abc = new int*[rows]; 

for (uint32_t i = 0; i < rows; i++) 
{ 
    abc[i] = new int[cols]; 
    std::fill_n(abc[i], cols, 1); 
} 

O rendere il tutto unidimensionale:

int *abc = new int[rows * cols]; 
std::fill_n(abc, rows*cols, 1); 

O Credo che si potrebbe utilizzare std::generate_n in combinazione con std::fill_n, ma questo sembra proprio confusione:

int **abc = new int*[rows]; 
std::generate_n(abc, rows, [cols]{ 
    int* row = new int[cols]; 
    std::fill_n(row, cols, 1); 
    return row; 
}); 
+1

@NathanOliver grazie! – Barry

3

credo che il problema principale è che non si dispone di una matrice di int valori. Hai una serie di puntatori a int s.

Probabilmente dovresti iniziare con int* abc = new int[rows * cols]; e lavorare da lì, se ho capito cosa stai cercando di ottenere qui.

2

Basta usare con * all'interno del ciclo si dispone già di:

for (uint32_t i = 0; i < rows; i++) 
{ 
    abc[i] = new int[cols]; 
    std::fill_n(*(abc+i), cols, sizeof(int)); 
} 

fill_n non so dove la memoria mappa il nuovo array int, quindi è necessario essere codifica con attenzione in questo modo.

vi consiglio di leggere: A proper way to create a matrix in c++

1

Dal momento che avete già buone, risposte praticabili per risolvere il problema, voglio aggiungere solo due puntatori a destra ea sinistra dal percorso standard ;-)

a) è solo un link alla documentazione di Boost.MultiArray

e b) è qualcosa che non consiglio di utilizzare, ma potrebbe aiutare a capire quello che hai provato inizialmente. E poiché il tuo profilo mostra i tag visual studio, puoi entrare in contatto con qualcosa di simile nell'API win32. In questo caso, la documentazione di solito ti dice di non usare free()/LocalFree()/... sugli elementi e il puntatore del puntatore "esterno" ma per usare una funzione specializzata.
(nota: non sto cercando di rendere questo codice guardare piuttosto o intelligente, è un miscuglio di c e un po 'C++ - spazzatura ish ;-))

const std::size_t rows = 3, cols =4; 

int main() 
{ 
    std::size_t x,y; 
    // allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints 
    int **abc = (int**)malloc((rows*sizeof(int*)) + cols*rows*sizeof(int)); 

    // the memory behind abc is large enough to hold the pointers for abc[0...rows-1] 
    // + the actual data when accessing abc[0...rows-1][0....cols-1] 
    int* data = (int*)((abc+rows)); 
    // data now points to the memory right after the int*-pointer array 
    // i.e. &(abc[0][0]) and data should point to the same location when we're done: 
    // make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1).... 
    for(y=0;y<rows; y++) { 
     abc[y] = &(data[y*cols]); 
    } 

    // now you can use abc almost like a stack 2d array 
    for(y=0; y<rows; y++) { 
     for (x=0; x<cols; x++) { 
      abc[y][x] = 127; 
     } 
    } 

    // and -since the memory block is continuos- you can also (with care) use memset 
    memset(&abc[0][0], 1, sizeof(int)*rows*cols); 

    // and with equal care .... 
    std::fill_n(&(abc[0][0]), rows*cols, 127); 

    // and get rid of the whole thing with just one call to free 
    free(abc); 

    return 0; 
}