Sto implementando un vettore in C. Lo sto facendo per il divertimento della programmazione, per il divertimento dell'apprendimento e per l'uso della struttura dei dati nei progetti successivi. Questo non è compito a casa. La mia domanda riguarda la metodologia, non necessariamente l'implementazione, quindi non sto davvero cercando una revisione del codice.
Ora ho letto molti esempi di implementazione e molti di loro prendono la dimensione di un singolo elemento come argomento per la funzione Vector_create()
, e la usano per chiamate memmove()
/ memcpy()
successive e cosa no e più o meno mantenere (per esempio) gli elementi del vettore nella memoria contigua. In altre parole, l'array sottostante è essenzialmente un singolo void*
.
Nell'implementazione che ho scritto prima di osservare molto in che modo gli altri lo hanno fatto, autorizzo (forza) il codice client ad allocare un "oggetto" e a passarlo come puntatore alla funzione Vector_append()
. Quindi il mio array sottostante è un void**
. Quindi immagino che la vera domanda che sto ponendo sia se è sbagliato. Sbagliato come nelle migliori pratiche sbagliate.
Vedo che il modo "normale" per farlo non usa una schiera di puntatori e invece copia semplicemente la memoria di una struct (ad esempio) nell'array void*
sottostante e mantenendo così i dati effettivi del elementi contigui, come accennato in precedenza. La mia strada evita un carico schifoso di memmove()
/ memcpy()
perché copio solo i valori del puntatore, tuttavia, sto forzando il client a malloc()
tutto ciò che viene inviato al vettore, e quindi faccio un sacco di avvitamenti sul mucchio.
Lungo queste linee, richiamo free()
sull'elemento di dati sottostante quando l'elemento viene rimosso, quindi la libreria vettoriale fa un free()
che la libreria vettoriale non ha mai fatto su malloc()
originale. Anche questa è una cattiva pratica? L'unico problema che mi sembra di capire è se ci fosse una variabile membro (per mancanza di un termine migliore) che punti alla memoria dinamica all'interno della struttura. Diventa quindi la responsabilità del cliente a free()
di quei dati, ma, di nuovo, la struttura stessa viene liberata dall'interno della chiamata della libreria vettoriale Vector_remove()
.