Newsgroup: it.comp.os.linux.development
Titolo: dubbi sui Pointer

Buongiorno
Avrei un problema:
Ho creato una classe con un attributo dinamcio ed il relativo distruttore
class nomeclasse {
char *nome;
nomeclass(int dim) { nome=new char[dim];}
~nomeclass() {delete nome[dim];}
};
 Ma quando tento di ritornare da una funzione un elemento di tipo nomeclass,
il compilatore mi da' un SEGMETATIO FAULT.
nomeclass Funzione() { nomeclass x; ...return x;}
 Ho capito che il problema e' il distruttore che viene chiamato prima
dell'uscita  della funzione, tanto più che eliminando il il corpo delete il
programma funziona bene.
Ma non deallocando nome[], manterrei tutti gli oggetti allocati con grande
spreco di memoria?
Una soluzione l'avevo trovato usando i Pointer
nomeclass *Funzione() { nomeclass *x;... return x;}
Ma visto che utilizzo anche degli overloading di operatori,questo metodo
rende esteticamente brutto la scrittura di codice, riducendo l'efficenza dei
operatori e rendendo più fastidiosa l'utilizzzo di pointer e no di tipo nome
class contemporanemante.
Spero che sappiate darmi una risposta o qualche consiglio me risolvere
questo problema.
Garzie Emanuele

 questo problema.
Fossi in te implementerei anche il costruttore di copia, altrimenti 
quando passi la tua classe per valore, ad esempio come param di una funz,
viene copiato pari pari anche il puntatore nome, e quando distruggi uno di questi oggetti, nome
punta ad un'area di memoria indefinita
bye
-- 
David
To err is human...to really foul up requires the root password.

 
char* nome;
nome e' ora un puntatore (un puntatore e' genericamente un indirizzo di 
memoria, pero' e' tipizzato e le aritmetiche ad esso associato seguono la 
segmentazione imposta dalla sizeof(tipo) in bytes).
new <data_type>;
il C, come il C++, e' linguaggio tipizzato, dunque tipi di dato primitivi 
(char, int, float) o astratti (struct, ... class in c++).
l'operatore new, ritorna sempre un pointer tipizzato secondo <data_type>.
char* nome = new char[dim]; // e' corretto in quanto un array e' descritto 
correttamente da un puntatore, ..., un puntatore al primo byte della 
regione di memoria in cui risiede l'array
delete <pointer>;
il sistema operativo riceve una operazione di deallocazione di una regione 
di memoria e sa lui di quanti bytes, tu gli passi il pointer e lui 
dealloca...
non ha senso delete nome[dim];, perche' indichi un char, non un char* cosi'.
PS. e' suggeribile andare a vedersi gli operatori di referenziazione e 
dereferenziazione del C, che valgono anche in C++ e le implicazioni e 
relazioni tra array []  e pointer. Tali operatori sono & ed *
&<variabile> -> restituisce l'indirizzo della variabile
Es:
int a; allora &a e' un pointer int, che in se ha l'address di mem della 
variabile a
e dunque puoi fare
int* ptr = &a; // ora ptr punta alla regione di memeoria di a
a, essendo un intero occupa sizeof(int) bytes, che se usi linux oggigiorno 
sono 4bytes, puoi verificarlo stampando una sizeof(int),come intero.
se tu hai l'indirizzo di a, registrato e salvato in un puntatore, ora, 
allora puoi modificare la variabile a, senza usare a, ma usando ptr, e come?
dereferenziando il puntatore
*ptr;
questo operatore * dereferenzia ptr, e ritorna la regione di memoria da lui 
puntata per una quantita' di bytes pari al tipo del puntatore stesso che 
essendo int*, sto ptr, e' di 4 bytes.
cosi'
se stampi *ptr, e come se stampassi a. e pure modificando *ptr = 5; e' come 
se avessi modificato a (a=5).
Relaazione con array:
int v[10];
qui' la memoria occupata e' 10 * sizeof(int) = (in linux) ... = 40 bytes.
quello che tutti i programmatori C, dovrebbero sapere e' la seguente 
relazione:
v[i] = *(v+i)
considera il fatto che e' stato introdotto il concetto di aritmetica dei 
puntatori in questo momento... infatti quando hai un puntatore, esso 
cos'e'? niente altro che un numero (se hai architettura a 4bytes->32bit, 
allora tutti i puntatori char*, int*, <type>*, sono interi a 32bit, infatti 
non devo fare altro che tenere un indirizzo di memeoria). In piu' un 
puntatore e' tipizzato e dunque da indicazione del tipo e della dimensione 
di quel tipo. Come e' rappresentato in memroria un vettore tipo il int 
v[10] ?
        v[0]         v[1]            v[2]           v[3]
       --------     --------        -------       --------
      |X| | | |    |Y| | | |      | | | | |       | | | | |
nota che le cellette sono a livello logico continue, ok ?
allora v, che cosa e' in tutto cio' ? e v[0] e v[1] ? e *v e *(v+i) ?
v e' l'indirizzo del byte contrassegnato dalla X, cioe' il primo byte.,
Ed e' per questo che una stringa char nome[dim]; non e' altro che un 
pointer char*, infatti e' legale fare un assegnazione del tipo
        char* ptr_nome = nome;
dove si fa capire che nome e' omogeneo al tipo char *.
Quando stampi la stringa, printf("%s\n", nome); passi il pointer, cioe' al 
primo elemento dell'array, poi la printf fa aritmetica del puntatore char 
spostandosi di un byte (dimensione del char) alla volta e dereferenziando 
ogni volta, per leggere (1 byte) il char.
Con il vettore v, hai l'address, con *v, dereferenzi (una quantita' di byte 
automaticamente data dal tipo del pointer, cioe' 4 byte) ed e' come se 
avessi scritto v[0]. Consistentemente con la fatidica relazione
        v[i] = *(v+i), che per i==0 e' *v
allora:
se vuoi v[1], avresti potuto scrivere invece *(v+1), e dove sta (v+1) ?
esattamente in Y, e questo perche' le addizioni/sottrazioni di numeri sui 
puntatori sono differentemente trattate e si basano sulla dimensione 
(sizeof(<type>)) del tipo.
Quando allochi dinamicamente mediante new, invece che staticamente con la 
dichiarazione tipo char nome[20]; hai
        char *nome = new char[20];
e dunque hai il pointer, che va deallocato passando all'operatore delete 
l'address della regione di memoria da cancellare, dunque l'address e' il 
pointer e dunque nome.
Ordunque... spero che qualche informazione sulla complessita' e coscienza 
di cio' che si ha sotto le mani quando si lavora in C, te l'abbia data...
bye
Lore