|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
|
[C++] Memory leaks for dummies
Ciao a tutti!
In vista di un esame ho deciso di "condividere" con voi tutti un paio di piccoli dubbi che mi attanagliano: Il primo riguarda i metodo set e get. Mettiamo il caso di una classe Persona che registri il nome di una persona, sotto forma di array char allocato dinamicamente. Non mi sembra conveniente far ritornare dal metodo get_nome() il puntatore, perchè poi potrei utilizzarlo per modificare arbitrariamente un membro private. Com'è corretto comportarsi? Pensavo di creare un char* temporaneo "temp" e di allocare una nuova stringa, ritornado questa. Il problema è che talvolta il metodo get_nome() potrebbe essere usato solo per stampare sul cout: in questo caso avrei allocato spazio che non potrei più recuperare... Il secondo riguarda la realizzazione in C++ della "inclusione lasca", ossia a mezzo di puntatore. Sia Persona una classe che definisce nome e età di una persona e Automobile una classe che contiene (in maniera lasca) una Persona. Realizzo un codice simile: Codice:
Persona* pippo = new Persona("Pippo", 23);
Automobile pippomachine("Opel Corsa", pippo);
Codice:
this->guidatore = pippo; In molti casi, nei compiti era richiesta la creazione di nuovi oggetti sulla base di oggetti preesistenti. In questo caso, per mantenere la relazione di "inclusione lasca", devo allocare un nuovo oggetto Persona copia di quello originale, o eseguire una "copia superficiale" del solo puntatore? Se creo un nuovo oggetto Persona, in questo caso il distruttore dovrebbe prendersi anche la responsabilità di deallocarlo: dovrei allora aggiungere qualcosa di molto poco carino come una variabile booleana che mi informa se l'oggetto contenuto è stato allocato in fase di copia o meno, in modo da inserire un controllo nel distruttore per eventualmente deallocarlo... ma mi sembrava abbastanza brutto Concettualmente non ho insomma ancora capito se, in caso di contenimento lasco (quindi a mezzo puntatore) è corretto copiare IL SOLO puntatore (quindi se modifico il "guidatore" della prima automobile modifico anche quello della seconda perchè sono sostanzialmente lo stesso) oppure se va realizzato ALLOCANDO un nuovo oggetto. Grazie a tutti per i consigli
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization. --Gerald Weinberg |
|
|
|
|
|
#2 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
per il primo problema basta ritornare un puntatore const:
Codice:
const char *get_name(); edit - anzi, oserei addirittura dire: Codice:
const char *get_name() const; |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
|
Quote:
A volte qualche assistente del prof mi ha fatto una capa tanta che è opportuno ritornare sempre una copia dell'elemento per non violare l'information hiding... effettivamente anche a me sembrava un po' pesante come storia
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization. --Gerald Weinberg |
|
|
|
|
|
|
#5 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
l'unico che ha il diritto di dire se è reato o meno è il compilatore, o al limite lo standard nei casi in cui i due si contraddicono; i professori spesso non hanno voce in capitolo.
prova ad implementare il prototipo che ti ho scritto e dimmi se ottieni errori di compilazione (frase retorica: io ho scritto mille volte cose del genere, mai il minimo problema). |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1270
|
Se ritorni un puntatore const il valore della stringa puo essere comunque modificato con un const_cast.
Io preferisco ritornare una copia per valore, un puntatore const lo prendo in considerazione solo se effettivamente si verifica un collo di bottiglia. |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
|
Sì ma se ho una stringa realizzata come char* e allocata dinamicamente come posso fare a copiarla senza "perdere" la memoria che alloco?
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization. --Gerald Weinberg |
|
|
|
|
|
#8 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1270
|
Quote:
Anche ritornando un puntatore const devi stare attento però: se l'oggetto che contiene l'array dinamico viene cancellato allora il puntatore che a cui è stato assegnato il valore di ritorno di get_name non contiene piu un indirizzo valido, e se viene usato da qualche altra parte rischi di avere qualche serio problema. La cosa piu semplice è creare una classe che gestisce la stringa e ritornarla per valore invece di usare direttamente un array dinamico. Ultima modifica di arara : 07-06-2008 alle 15:43. |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2780
|
Veramente nel link che avevo postato c'era la soluzione al problema, anche se la trovo un po' scomoda da realizzare
|
|
|
|
|
|
#11 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
se proprio si vuole evitare di ritornare il puntatore const (soluzione più che decente secondo me) come soluzione ci sarebbe quest'altra (scrivo dichiarazione ed implementazione delle classi in un unico sorgente per fare prima):
Codice:
class CName
{
private:
char *Content;
public:
CName(const char *Data)
{
size_t Size = strlen(Data) + 1;
Content = new char[Size];
memcpy(Content, Data, Size);
}
~CName()
{
delete Content;
}
operator const char* ()
{
return Content;
}
};
class CNamed
{
private:
char *Name;
public:
CName GetName()
{
return Name;
}
};
.
.
.
CNamed NamedObject;
.
.
.
cout << NamedObject.GetName(); // nessun leak
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:11.




















