Sto scrivendo un elenco collegato in C
.
list.h
typedef struct list_struct * List; /* Defined in list.c */
List create_list();
void destroy_list(List list);
void list_add(List list, void * item);
void list_remove(List list, int is_target(void *));
... /* Other handy functions like 'list_size', etc. */
list.c
typedef struct node_struct
{
void * item;
struct node_struct * next;
} * Node;
typedef struct list_struct
{
Node head;
... /* Other handy things like size, tail, etc. */
} List;
void list_remove(List list, int is_target(void *))
{
... /* Find target node to delete. */
free(target->item);
... /* Update links. */
free(target);
}
... /* Other functions definitions. */
list_remove
: quando rimuovi un Node
(è usato dietro le quinte in list.c
), devo ovviamente deallocarlo (usando free
). Tuttavia, prima di liberare Node
, dovrei anche liberare l''elemento' che contiene?
My Take
Pro: Il vantaggio di liberare l'elemento è che un client che utilizza questa API non deve tenere traccia degli elementi che archivia in un 'elenco'. Inoltre, non avrebbe dovuto preoccuparsi di liberare l'oggetto da solo.
Contro: se il client desiderava utilizzare l'elemento dopo l'eliminazione del nodo, non può perché è stato distrutto. Ecco perché liberare l'oggetto potrebbe essere una cattiva idea.
Soluzione: modifica la funzione in void * list_remove(List list, int is_target(void *))
(nota che ora restituisce void *
). Restituisce l'oggetto nel nodo (il nodo stesso viene distrutto). Quindi, se il cliente decide che non ha bisogno dell'elemento, può semplicemente chiamare free(list_remove(my_list, homework_that_dog_ate("HW 5")));
. E, se vuole tenerlo, può Homework dog_food = list_remove(my_list, homework_that_dog_ate("HW 5"));
.
La mia soluzione è buona? Se no, dov'è il problema? C'è un approccio migliore?