Newsgroup: it.comp.lang.c++
Titolo: [Help]Liste

Come faccio con la routine di distruzione per le liste
Class list
{
void insert(void*,int);
void* remove(int);
void* first(void);
// (e altre)
}
Class nodo
{
void* data;
struct nodo* next;
}
    Ciao e grazie

 wrote in message news:85qon5$tal$1...@pegasus.tiscalinet.it...

Dato un "void*", e non sapendo come e` stato allocato, a cosa
veramente punta, eccetera, non vi e` un modo generale per
rilasciarlo.  La tua "class list" (nota che C++ e` case-sensitive,
e Class con C maiuscola non significa assolutamente nulla) non
e` dunque in grado di gestire il rilascio di questi dati (cosi` come
non puo` duplicarli nella insert, eccetera).
Perche` non fai un bell'#include <list> e usi poi std::list<qualcosa>
invece di una classe fatta in casa...?  std::list<>, essendo un
template, ha tutte le informazioni necessarie per gestire gli
oggetti (di tipo arbitrario purche` canonico) che mantiene.
Alex

 oggetti (di tipo arbitrario purche` canonico) che mantiene.
Mi spieghi cosa intendi con "tipo arbitrario purché canonico"? Quali sono i
tipi "non canonici" che quindi non possono essere utilizzati con
std::list<>?
Grazie
-----
Giovanni Bajo
Lead Programmer
Prograph Research S.r.l.
http://www.prograph.it

 std::list<>?
Un tipo e` canonico se non e` astratto ed ha versioni accessibili di:
costruttore di default, costruttore di copia, assegnamento di default,
distruttore.
Si noti che questo comprende i tipi built-in, come ad esempio i
puntatori.  Ma non comprende, ad esempio:
    class Peep {
        private:
            Peep(const Peep&);    // copy ctor privato
            ~Peep();                    // dtor privato
            friend class Feem;      // ...accessibile solo a Feem
            void operator=(const Peep&);    // assignment privato
        public:
            Peep(double d);          // niente default ctor
    };
Non tutti i 4 elementi suddetti sono necessari perche` un tipo
possa far parte di ciascuno dei template-contenitori delle
librerie standard C++ (e non tutti i compilatori sono in grado
di capire esattamente quali di essi sono necessari per ogni
dato, specifico set di feature di un contenitore che vengono
poi usate nel programma, anche se, a rigore, lo standard lo
richiederebbe).
Ad esempio, il distruttore dev'essere accessibile perche` il
contenitore, quando viene distrutto, distrugge a sua volta
gli elementi.  Un copy ctor sara` normalmente necessario
(riesce difficile pensare a un programma che usa uno
std::list ma nessuno dei suoi vari push_back, push_front,
insert, ecc ecc, ciascuno dei quali naturalmente richiede
un copy ctor).  Un default ctor, a rigore, potrebbe non
essere necessario se il programma non fa uso di nessuna
delle funzioni di std::list che lo richiedono (resize con 1
solo argomento, assign con 1 solo argomento, insert con
1 solo argomento, ...), ma non mi sorprenderebbe se un
dato compilatore non fosse in grado di fare a meno del
default ctor (cioe` di dimostrare per ciascuno dei casi in
cui esso appare come argomento di default che non viene
davvero usato, ecc, ecc).
Alex

 davvero usato, ecc, ecc).
Hmm sì questo dipende proprio dalla struttura interna del compilatore...
Bye


std::list<>?
Immagino che con "canonico" intendesse un tipo che soddisfa i
requisiti richiesti da std::list<> (che sono veramente minimi).
Paolo

 errore, è un comportamento conforme allo standard?
Se dichiari un oggetto e non lo definisci sei in violazione della
one-definition rule, cosa che il compilatore non e` in tutti i casi
tenuto a diagnosticare.  Se dichiari un tipo e non definisci (e
neppure dichiari) nessuna istanza di quel tipo la situazione e`
drasticamente diversa.  In altri termini, col tipostrano suvvisto:
    typedef std::list<tipostrano> listastrana;
Un programma che consiste di questa sola riga (piu` la
dichiarazione di tipostrano, l'#include di <list>, e un main
vuoto) non viola nessuna regola; a rigore, dunque, un
compilatore dovrebbe accettarlo (anche se in pratica una
comune e lieve violazione dello standard sarebbe quella di
rifiutarlo -- approccio sensato, visto che non ha nessuna
possibile utilita` definire un tipo inutilizzabile anche se non
lo si utilizza; almeno un warning sarebbe dunque gradito!-).
Se aggiungiamo
    extern listastrana krek;
senza definire ne` usare krek da nessuna parte, abbiamo violato la
O-D-R nel tipico modo che un compilatore non e` rigorosamente
tenuto a diagnosticare.  Puo` essere dunque compliant sia un
compilatore che diagnostica l'errore, sia uno che lo trascura.
Se aggiungiamo invece
    listastrana kruk;
abbiamo una violazione dell'accessibilita` (del distruttore di
tipostrano) e sarebbe non-compliant per il compilatore non
diagnosticarla.
Alex

     typedef std::list<tipostrano> listastrana;
Anche questo è accettato dal VC, purché ovviamente non venga definita
nessuna istanza. Se invece dichiari un'istanza di questo tipo senza
definirla, siamo di nuovo in ODR violation, ma ignorata silenziosamente dal
VC.
Ciao
-----
