Newsgroup: it.comp.lang.c++
Titolo: Puntatori in C++

Ciao a tutti! Sono alle prime armi nella programmazione in C++! Sto
frequentando il primo anno del Diploma d'Informatica a Pd. Volevo solamente
togliermi una curiostà! Questi benedetti Puntatori servono veramente? Pare
che per il mio prof esistano solo quelli! Per quel che ne ho capito io, è
mooolto più semplice usare i riferimenti... e si sbaglia di meno!
Se qualcuno ha voglia di scrivere 2 righe gliene sarei grato!
CIAO!

 wrote in message
8vo3hm$7gg$1...@nread1.inwind.it...

Sono fondamentali per la gestione della memoria Dinamica!
Vedi new e memoria dinamica, più avanti magari ti accorgerai della potenza.
Tutti i linguaggi di programmazione per windows ti forniscono dei puntatori
agli oggetti visuali!
Prova ad usare il Borland C++ bulider e te ne accorgerai!

 Se qualcuno ha voglia di scrivere 2 righe gliene sarei grato!
ciao,
i puntatori sono sicuramente utili in più di una occasione, ma secondo
me sono meno importanti di quanto non lo fossero in C. Forse insiste
perchè generalmente i puntatori sono l'argomento più difficile da
comprendere per i nuovi iniziati, o forse perchè lui stesso ha
programmato in C per il 99% del suo tempo e questo lo condiziona un
po' (può sempre essere).
Se è più semplice usare i riferimenti non lo so, forse hai ragione tu,
ma a me la sintassi dei puntatori piace, per qualche recondito motivo
personale... scrivere oggetto->metodo() è secondo me artisticamente
più bello che oggetto.metodo(), sarà per l'insignificanza del punto di
fronte alla maestosità della freccetta? mah!

Per quel che ne ho capito io, č mooolto piů semplice usare i riferimenti...
I riferimenti sono in realta' dei puntatori camuffati.
Se si sbagli meno non lo so, ma una cosa e' certa : i puntatori hanno
un ruolo fondamentale sia in C, che in C++.
--
Andrea Laforgia (ICQ 87230455)
"A C program's trick is sometimes a C++ program's trap"
                                          [S.B.Lippman]

I puntatori avevano un ruolo fondamentale prima dell'avvento della
libreria standard, che li rende molto meno importanti. Il tuo professore
farebbe bene ad aggiornarsi ed a "svecchiare" il suo corso.
Ciao,
Nicola

 un ruolo fondamentale sia in C, che in C++.
Ne avevo avuto la sensazione! Ora io, come avevo scritto, ho cominciato a
studiare C++ 2 mesi fa e quindi non so che cosa mi aspetterà più avanti! Per
quel che ne so ora, tutto ciò che abbiamo programmato con i puntatori si
poteva fare anche senza! Oddio, ammetto che veniva su un programma un
po'incasinato, ma era fattibile!




ma come la metti con ereditarieta' e polimorfismo?

 ma come la metti con ereditarieta' e polimorfismo?
Che vanno insegnati *prima* dei puntatori.
Ciao,
Nicola

Che vanno insegnati *prima* dei puntatori.
Il polimorfismo va insegnato prima (???) dei puntatori ?
-- 
Andrea Laforgia (ICQ# 87230455) ---------------------------
Non scrivetemi in privato, se non richiesto espressamente.
No replies in private e-mail, unless explicitly requested.
----------------------------------------------------------

 Il polimorfismo va insegnato prima (???) dei puntatori ?
E perche' no? Con la libreria standard ed i reference i puntatori
diventano a mio avviso un argomento piu' avanzato del polimorfismo.
Ciao,
Nicola

diventano a mio avviso un argomento piu' avanzato del polimorfismo.
Mah, non so, il tuo potrebbe essere l'approccio migliore.
Io pensavo che, dato che il polimorfismo entra in gioco proprio con
reference e puntatori, fosse bene capire, anzitutto, cosa e' un
puntatore. Anche se io sono convinto che gli argomenti non siano
difficili in se', e' difficile insegnarne la loro semplicita'.


 difficili in se', e' difficile insegnarne la loro semplicita'.
Se il C non esistesse, sarei perfettamente d'accordo con te. In realta'
penso che uno dei piu' grossi ostacoli alla comprensione del C++ moderno
sia l'idea che uno debba imparare prima il C e poi il "++".
Per questo ritengo sia importante uno sforzo particolare per
"capovolgere" questo punto di vista.
Bisogna pero' riconoscere che il linguaggio stesso non aiuta, poiche'
non e' piu' possibile scrivere "Hello, World!" senza incocciare in
problemi un po' esoterici, almeno per i principianti, come i namespace.
Ciao,
Nicola

problemi un po' esoterici, almeno per i principianti, come i namespace.
Gia'. Il problema e' che uno dovrebbe cominciare a fare cio' che gli
serve nel modo piu' semplice e poi, magari, approfondire.


"capovolgere" questo punto di vista.
Veramente non comprendo questa necessita'. I puntatori sono
semplicissimi da comprendere... ovviamente se uno ha almeno
una vaga idea di cosa sia la memoria di un computer e come
sia organizzata.
Insegnare il C++ a qualcuno che non ha la minima idea di cosa
sia la memoria del computer e' secondo me come insegnare le
derivate parziali a chi non sa contare.
Ma poi cosa c'e' di cosi' terribile nei puntatori ?
Il discorso sarebbe diverso se il linguaggio fosse un altro
e non il C++, che, a differenza di lisp, vb, perl o java
*NON* crea un mondo virtuale per il programma in cui
dettagli come la memoria non esistono.
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 problemi un po' esoterici, almeno per i principianti, come i namespace.
Non credo che un 'principiante' inizi a programmare in C++, io ho fatto un
bel pò di gavetta col BASIC e col Pascal e non ho avuto alcun problema,
anche se quando ho iniziato a studiare il C++ i namespace non esistevano
ancora. Ma non esisteva ancora neppure la nuova standard library, e quindi
ho imparato il C++ "nudo e crudo", poi mi sono "aggiornato". Certo la
libreria standard oggi offre tante comodità, ma un programmatore C++ degno
di questo nome deve sapere anche far meglio di tale libreria (a volte si
può, ma non si può pretendere di farlo senza conoscere le low-level-features
del C++).
Ciao
Domenico

sia organizzata.
Boh, io per capire i puntatori non ho avuto molti problemi... invece non ho
avuto la stessa fortuna con le liste, liste doppiamente linkate etc...
-- 
Posted from [195.223.215.6] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

avuto la stessa fortuna con le liste, liste doppiamente linkate etc...
Questo e' un discorso diverso... il puntatore e' in se semplice
ma le strutture dati che si possono realizzare usandolo possono
essere sicuramente complesse e di non immediata comprensione.
Io confesso di essere un maniaco delle liste doppiamente
collegate (anzi... della struttura "net" in cui ogni elemento
appartiene a piu' liste contemporaneamente ed e' proprietario
di piu' liste). Questo non toglie che la comprensione dei
*puntatori* (non cioe' di tutte le possibili strutture dati
che si possono realizzare con essi) sia qualcosa che non
richiede grandi sforzi e sia (a mio parere ) molto molto
importante in un linguaggio come il C++.


 avuto la stessa fortuna con le liste, liste doppiamente linkate etc...
Ecco il punto. Mentre sui puntatori sono almeno in parte d'accordo con
Andrea Griffini, con l'avvento della libreria standard, la necessita' di
costruirsi strutture dati ad hoc e' molto diminuita. In questo senso mi
pare meglio imparare *prima* a usare quello che gia' c'e' e *dopo* a far
da se se quello che gia' c'e' non e' adeguato.
Ciao,
Nicola

 del C++).
Il problema e' che esistono tanti programmatori C++ che si credono degni
di questo nome ed invece non lo sono, e questi individui farebbero molto
meglio ad imparare ad usare bene cose fatte da gente piu' in gamba di
loro, che avere la presunzione di far meglio al primo colpo.
 
L'aspetto che veramente distingue il C++ da quasi tutti i linguaggi a
lui somiglianti (Java, Delphi, C#,...) e' il fatto di poter essere usato
a due velocita': i programmatori meno esperti possono (e dovrebbero)
limitarsi a comporre insieme elementi costruiti dai programmatori piu'
esperti o acquisiti fuori.
Cio' e' possibile perche' il linguaggio mette a disposizione dei
programmatori esperti tutti i suoi elementi (vedi ad es. l'overload
degli operatori); all'opposto ad esempio ci sono le funzioni di I/O del
Pascal originale, le uniche che supportassero l'overload ed il numero
variabile di parametri.
Allora ritengo sia meglio che chi si accosta al linguaggio impari prima
ad usare quello che gia' c'e' (col quale un po' di strada la si puo'
comunque fare) e poi a far da se quello che manca.
Ciao,
Nicola

che verra' in seguito, invece che imparare ad usare i puntatori.
Vero. Ho notato che questo, tra l'altro, e' l'orientamento di alcuni
testi sul linguaggio (come C++ Primer).
--
Andrea Laforgia (ICQ 87230455)
------------------------------ 
#exclude <windows.h>

comunque fare) e poi a far da se quello che manca.
Sicuramente in C++ c'e' molta piu' roba disponibile...
e si tratta di cose che sono state scritte per essere
utilizzate (anche leggermente a sproposito).
Personalmente ad esempio mi sono trovato ad usare
std::map per trovare tutti i nomi univoci dei pezzi
in un elenco e non me ne vergono anche se sicuramente
da un punto di vista di cicli macchina si e' trattato
di uno spreco (a me bastava una hash table... nessuno
mi aveva chiesto l'ordinamento).
Valeva la pena scriversi una hash table per una
importazione da file ascii di un elenco di 100-200 pezzi
con 10-20 nomi univoci ? A mio parere no. In 30 secondi
con std::map ho risolto brillantemente il problema.
Riguardo agli algoritmi ancora non mi sono abituato...
tu si ?
Io trovo che usare gli algoritmi quando non e' possibile
avere delle closures come quelle del Clipper 5 o del
PERL rende la scrittura del codice complessa...


 PERL rende la scrittura del codice complessa...
Questo e' un problema che col C++ e' ricorrente: l'impatto dei costrutti
o dei paradigmi che lo compongono non sono mai esplorati fino in fondo,
per cui spesso ci si imbatte in contraddizioni, ambiguita' o anche solo
semplici scomodita'. Io penso che Stroustrup abbia un po' esagerato con
la sua avversione all'eleganza fine a se stessa.
Ciao,
Nicola

 PERL rende la scrittura del codice complessa...
Che cosa intendi con "closures"?
EMG

> PERL rende la scrittura del codice complessa...
Se il C++ fosse simile al clipper in questo aspetto si
almeno si potrebbero scrivere cose come
  find_if(c.begin(),c.end(),{|x| x<7});
Comunque brutte... ma meglio di bind2nd(less<int>(),7).
E perche' non avere anche una find_if che lavora su
tutto il contenitore ? Penso che sia un caso molto
comune... il codice diventerebbe:
  find_if(c,{|x| x<7});
o meglio ancora
  find_if(c,{ @ < 7 })
Mi sa che se mai scrivero' un altro compilatore questa
roba provero' a buttarla dentro :DDD
Tornando al C++ ho notato che degli algoritmi parlano
in pochi. Non credo che sia qualcosa che sta prendendo
piede (che sia un bene ?).


Che cosa intendi con "closures"?
Non so se e' il termine tecnico corretto. Mi sembra comunque
di averlo visto usato con questo significato...
Faccio un esempio PERL
  sort { $hits{$a}<=>$hits{$b} } keys %hits
Questa espressione restituisce l'elenco di chiavi di un hash
(immaginalo simile an un std::map) ordinate in base al valore
(e non alla chiave). Nota che questo non avviene per "magia"
del compilatore PERL e che anche funzioni utente possono
ricevere dei parametri che sono di tipo "codice".
Si tratta in un certo senso di puntatori a funzione solo
che sono funzioni senza nome definite al momento in cui
vengono usate.
In realta' si tratta di piu' che puntatori a funzione;
considera questo esempio ipotetico C+++
 int total;
 traverse_tree(t,{|tree_node& x| total+=x->value;});
immagina che la funzione traverse_tree permetta di visitare
tutti i nodi di un albero passando ogni singolo nodo ad
una funzione di una variabile.
Questa funzione l'ho definita "in place" ma c'e' anche
un altro punto importante: nella funzione accedo anche a
total che e' una variabile locale.
In C++ si riescono a fare cose simili usando function
object e classi locali ma la sintassi e' molto pesante
anche per casi semplici. Es:
  int total=0;
  struct MyVisitor : TreeNode<int>::Visitor
  {
    int& total_;
    MyVisitor(int& t) : total_(t)
    { }
    void Visit(TreeNode<int>& n)
    {
      std::cout << n.v << std::endl;
      total_+=n.v;
    }
  } myv(total);
  root->Traverse(myv);
  std::cout << "total = " << total << std::endl;
 
Il frammento precedente usa un metodo di una classe
TreeNode che permette di far visitare l'albero ad
un oggetto che sia di tipo TreeNode::Visitor di cui
viene chiamato il metodo Visit per ogni nodo.
Con una classe locale viene costruito un visitatore
che stampa il contenuto dell'albero e ne calcola
il totale (in una variabile locale(!) del main).
Questa cosa con a disposizione le closures diventerebbe
  int total=0;
  root->Traverse({ |TreeNode& x|
                   std::cout << x << std::endl;
                   total+=x; });
  std::cout << "total = " << total << std::endl;
Oltre alla complessita' sintattica richiesta per poter ottenere
lo stesso effetto anche in C++ io ho incontrato anche problemi
di compilazione quando uso delle classi locali; ad esempio il
programma da cui ho tratto il frammento compila con g++ ma
da un errore di link se richiedo l'ottimizzazione (!).
Per risolvere devo necessariamente spostare la definizione
della MyVisitor fuori dal main... BCC55 non ha invece problemi
a compilare il tutto.
Inoltre non ho visto usare molto le classi locali... forse si
tratta di un'altra di quelle zone d'ombra dello standard C++
in cui non tutto e' ben chiaro su come debbano essere
implementate le cose.
Implementare le closures non e' banale e questo forse spiega
perche' non facciano parte del C++ (uno di questi oggetti
potrebbe vivere piu' a lungo del blocco in cui le variabili
sono state definite: tutte le implementazioni che ho visto si
basavano su reference counting su tutte le variabili,
incluse quelle locali... questo sarebbe inaccettabile in C++
per questioni di prestazioni).
HTH


 piede (che sia un bene ?).
Non penso che sia un bene, perche' in molti casi sono implementati in
modo efficiente per compilatori che sanno espandere in linea in modo
passabile. Ed ho orrore di chi rifa' centomila volte le stesse cose
(anche perche' in una buona parte dei casi ci infila degli errori).
Ciao,
Nicola

 per questioni di prestazioni).
Infatti il Clipper si basa su garbage collector e (sicuramente) su
reference counting, anche se in modo totalmente trasparente.
EMG

(anche perche' in una buona parte dei casi ci infila degli errori).
Mah... io sulle espansioni in linea mi sono scottato qualche volta...
ad esempio BCC55 aggiunge un paio di KB ogni volta che *usi* una
map<string,string> in una istruzione del tipo
  m["Andrea"]="Griffini";
Che avranno infilato in quelle 400 istruzioni assembler in cui si
espande questa riga di codice ? Boh... forse c'e' l'inserimento
nel red-black tree inline...
Riscrivendomi string e map (reinventando cioe' la ruota) il codice
dell'applicazione e' diventato un decimo (e non e' una applicazione
che assegna solo stringhe).
In fondo sperare di fare *tutto* compile time mi sembrerebbe un
po' come pensare di sostituire le subroutine con le macro.
Per tornare al punto degli algoritmi pero' io credo che al momento
siano molto scomodi da usare... se solo i template accettassero
dei parametri di tipo "expression" o "statement block" forse la cosa
sarebbe diversa.


 sarebbe diversa.
Qui il discorso e' complesso: in effetti l'abbondare di classi
funzionali usa e getta porta a desiderare sia un meccanismo per la
definizione "sul posto" di classi anonime, sia l'introduzione degli
scope dinamici innestati (ovvero la visibilita' delle variabili locali
della funzione contenente) come esistono in Pascal. Ma non penso che
succedera'.
Ciao,
Nicola

succedera'.
Scusa, non ho capito quello che hai scritto: mi puoi fare un esempio
(anche in Pascal, visto che lo conosco)?
Anto

(anche in Pascal, visto che lo conosco)?
Credo si riferisca a situazioni come nell'esempio seguente :
procedure MyProcedure ;
var I : Integer ;
   procedure IncLocal( var Step : Integer ) ;
   begin
     I := I + Step ;
   end ;
begin
  IncLocal( 2 ) ;
end ;


Esattamente. Se non sbaglio le "inner class" del Java funzionano allo
stesso modo, ovvero "vedono" le variabili locali del metodo da cui sono
chiamate.
Ciao,
Nicola