PDA

Visualizza la versione completa : [C++] Problema puntatori


Neptune
19-11-2010, 20:53
Salve a tutti,
per motivi di astrazione ho bisogno di trasformare queste due dichiarazioni



void inslista(tipoelem,posizione&);
void canclista(posizione &p);


In:



void inslista(tipoelem,posizione);
void canclista(posizione p);


Riferite al seguente codice (ovvio che bisogna adattare il codice alle dichiarazioni):




template <class A>
void ListaP<A>::inslista(tipoelem a, ListaP::posizione &p)
{
typename ListaP<A>::posizione temp;

temp = new Cella<A>;
temp->setElemento(a);
temp->setPrec(p->getPrec());
temp->setSucc(p);
(p->getPrec())->setSucc(temp);
p->setPrec(temp);
p=temp;
}

template <class A>
void ListaP<A>::canclista(ListaP::posizione &p)
{
typename ListaP<A>::posizione temp;

temp=p;
(p->getSucc())->setPrec(p->getPrec());
(p->getPrec())->setSucc(p->getSucc());
p=p->getSucc();
delete(temp);
}


Questo perchè ho creato una classe con delle funzioni su liste che deve funzionare su più tipi di realizzazioni che ha appunto, tra i metodi virtuali le dichiarazioni senza i puntatori.

Mi chiedevo quindi se c'era un modo di cambiare il codice di sopra, io non sono molto ferrato con i puntatori e sto impazzendo.

Vi ringrazio in anticipo,
Neptune.

MItaly
19-11-2010, 21:09
Quei "posizione &" non sono puntatori, ma reference, i quali, pur essendo dei puntatori nascosti, di fatto hanno la sintassi di normali variabili "by value". Quindi, puoi togliere l'& senza problemi, la sintassi non cambia.
Piuttosto, tieni presente che in questa maniera passi da passaggio by reference a passaggio by value, che, se può avere senso per gli indici (che non dovrebbero essere roba pesante), per gli oggetti da memorizzare sarebbe da evitare, perché il passaggio by value nella funzione richiede una ulteriore copia inutile.

Neptune
19-11-2010, 21:23
Originariamente inviato da MItaly
Quei "posizione &" non sono puntatori, ma reference, i quali, pur essendo dei puntatori nascosti, di fatto hanno la sintassi di normali variabili "by value". Quindi, puoi togliere l'& senza problemi, la sintassi non cambia.
Piuttosto, tieni presente che in questa maniera passi da passaggio by reference a passaggio by value, che, se può avere senso per gli indici (che non dovrebbero essere roba pesante), per gli oggetti da memorizzare sarebbe da evitare, perché il passaggio by value nella funzione richiede una ulteriore copia inutile.

Conta che in questo caso quel "posizione" sarebbe una typedef di un oggetto di tipo cella si fatto:



template <class T>
class Cella
{

public:
typedef T tipoelem;
void setElemento(tipoelem);
tipoelem getElemento() const;
void setSucc(Cella *);
Cella * getSucc() const;
void setPrec(Cella *);
Cella * getPrec() const;
private:
tipoelem elemento;
Cella * prec;
Cella * succ;
};



Ma cosi facendo non ho capito bnee, contando che sono funzioni "che modificano la lista", ovvero cancellamento ed inserimento di un nuovo elemento, le operazioni vengono fatte ugualmente e rimangono permanenti anche senza quell'operatore di reference?

MItaly
19-11-2010, 21:27
Originariamente inviato da Neptune
Conta che in questo caso quel "posizione" sarebbe una typedef di un oggetto di tipo cella si fatto:

Non ha importanza.

Ma cosi facendo non ho capito bnee, contando che sono funzioni "che modificano la lista", ovvero cancellamento ed inserimento di un nuovo elemento, le operazioni vengono fatte ugualmente e rimangono permanenti anche senza quell'operatore di reference?
Se i reference che togli sono solamente riferiti a dei parametri delle funzioni e sono parametri di solo input (non vengono cioè scritti nella funzione per modificare gli oggetti originali) non dovrebbe cambiare nulla, a parte il fatto che nel momento in cui viene richiamata la funzione ne viene creata una copia invece di essere passato un riferimento all'oggetto originale.

Neptune
19-11-2010, 21:28
Semplicemente cancellandoli i reference non va.

Appena faccio un operazione del genere:



ListaP<int,Cella<int> *> l2;
l2.inslista(12, l2.primoLista());


Dove il metodo primoLista è questo:



template < class T, class P >
typename ListaP<T,P>::posizione ListaP<T,P>::primoLista() const
{
return lista->getSucc();
}


il programma crash.

MItaly
19-11-2010, 21:30
'scolta, così ci capisco poco, prova ad incollare il tutto su ideone.com (http://ideone.com/) così vediamo cosa succede.

Neptune
19-11-2010, 21:36
Originariamente inviato da MItaly
'scolta, così ci capisco poco, prova ad incollare il tutto su ideone.com (http://ideone.com/) così vediamo cosa succede.

Ho incollato libreria e main in un unico fail per farti vedere "il debug" anche se non dice nulla di significatico:

http://ideone.com/xKqEK

Neptune
19-11-2010, 21:42
Piccola mappa:

A linea 19 trovi la classe padre, liste collegate che ha i metodi di visualizzazione e modifica delle strutture virtuali, mentre implementa tre funzioni sue;

A linea 105 trovi invece ListaP che è invece la realizzazione delle liste con puntatore;

Infine a linea 133 trovi la realizzazione con cursore;

I metodi che danno problemi sono inslista() e canclista(), che nella versione con cursore richiede una posizione di tipo intera, mentre nella versione con puntatore un reference alla classe cella.

MItaly
19-11-2010, 22:35
Ok, errore scovato (almeno, senza questo non va in crash, non ho guardato bene il resto).
Nel main non richiami crealista(), per cui la sentinella non viene mai creata, dunque primoLista restituisce roba a caso, e al primo tentativo di dereferenziarlo esplode tutto. Dovresti fare in modo che il costruttore di default della superclasse richiami il metodo virtuale crealista, così che dopo che qualunque oggetto derivato è stato costruito esso è pronto all'uso.

Neptune
19-11-2010, 22:45
Originariamente inviato da MItaly
Ok, errore scovato (almeno, senza questo non va in crash, non ho guardato bene il resto).
Nel main non richiami crealista(), per cui la sentinella non viene mai creata, dunque primoLista restituisce roba a caso, e al primo tentativo di dereferenziarlo esplode tutto. Dovresti fare in modo che il costruttore di default della superclasse richiami il metodo virtuale crealista, così che dopo che qualunque oggetto derivato è stato costruito esso è pronto all'uso.

Cavolo, mi faccio fregare ogni volta da quel crealista :dhò:

E' che quella bellissima realizzazione me l'ha passata il professore e mi chiedo anch'io il perchè di quel "crealista", non potrebbe semplicemente utilizzare il costruttore per crearla?

Ad ogni modo ho creato un costruttore che lancia il crealista e amen.

Mi spieghi però ben benino come fa a funzionare in maniera totalmente uguale anche se invece di passargli un reference ad un oggetto gli passo un oggetto direttamente? ovvero senza quegli & ?

Loading