Newsgroup: it.comp.lang.c++
Titolo: Il C++ secondo Soustroup

Salve!
Da vero neofita del C++: alla mia domanda:<<Mi dia un buon libro  su
C++>>, il Libraio ha reagito sommergendomi letteralmente di volumi. Alla
fine, esausto ho scelto il tomo del suddetto padre del C++. Quasi mille
pagine. Ho fatto bene? (centocinquemilalireeeeeeee)
grazie.
Droide.

...

Se e` la terza edizione (la piu` recente), penso di si`; forse non il
migliore libro per alcuni _specifici_ scopi, ad esempio per un
principiante che voglia solo imparare il linguaggio, ma il migliore
*nel complesso* -- per avere una piu` generale *presentazione*
del linguaggio, suoi scopi, esempi d'uso, ragioni dietro alcune
delle scelte che lo hanno portato ad essere com'e`, cenni sul
come e perche` si progettano librerie e applicazioni, ecc ecc,
oltre all'elemento "apprendimento"...
Alex


Grazie.
Ho l'ultima edizione in inglese e a parte qualche punto poco chiaro (per
esempio la differenza che sussiste fra passare i parametri di una funzione
come reference o come valore, ma in generale è la "type& varname" che mi è
poco chiara) direi che la materia la insegna, almeno nei suoi fondamenti, non
nei tricks.
Ogni ulteriore consiglio eè il benvenuto.
Grazie.
Ciao
 Droide.

 nei tricks.
La storia del valore/reference e' uno dei tormentoni eterni dei
linguaggi di programmazione....(fortran docet, l'unico linguaggio dove
era possibile cambiare il valore di 2 :).
In poche parole l'idea e' questa: quando chiami una funzione
passandogli una variabile (diciamo per esempio un intero) COSA viene
realmente passato?
Ci sono due possibilita' (almeno ;):
1) viene passato il valore dell'intero, che viene quindi copiato in
una variabile locale, distrutta alla fine dell'esecuzione della
funzione.
2) viene passato un "puntatore" alla variabile intero che io sto
passando. L'effetto quindi e' che la mia variabile locale in effetti
NON e' una variabile locale, ma un "sinonimo" della variabile che e'
stata passata.
Esempio: caso 1:
void stronka(int v)
{
  v = 75;
}
.....
  int b = 17;
  stronka(b);
  <stampa il valore di b>;
.....
Qui quello che accade e' che nella funzione stronka la variabile v e'
una variabile locale, il 17 che sta in b viene preso e copiato dentro
v. [nota avanzata: v viene creata al momento di entrare in stronka
usando un copy constructor, poi viene cancellata, tipo delete,
chiamando il destructor alla fine dell'esecuzione di stronka].
Eseguendo il programma quando si stampa il valore di b si ottiene 17.
V e' stata creata assegnandogli 17, poi qualcuno gli ha assegnato 75 e
poi e' stata distrutta. RIP.
Esempio: caso 2:
tutto come prima, ma stronka e' definita cosi':
void stronka(int& v)
{
  v = 75;
}
Qui l'esecuzione del programma genera un bel 75 in fase di stampa e
NON 17. La ragione e' che in questo caso alla funzione stronka e'
stata passata non una copia della variabile b, ma "la variabile essa
stessa". All'interno della funzione tu la chiami v, ma in effetti
quella E' b. [nota: nessuna chiamata di copy constructor: non si e'
costruito proprio nulla!].
Se lo confronti con gli esempi scazzoni delle reference vedrai che e'
la stessa cosa di quando dichiari:
int a = 25;
int& b = a;
in effetti quello che stai dicendo e' che b e' la stessa cosa di a. E'
un "sinonimo", sono due nomi che puntano alla stessa locazione di
memoria....vedi quale interpretazione preferisci.
Da qui si capiscono i vantaggi (e i pericoli) del passare reference
invece che valori:
- quandi passi un valore viene fatta una copia: per un intero questo
non prende molto tempo, ma per un oggetto ti una classe
incasinatissima magari si. Passare reference accelera (o almeno puo'
accelerare) notevolmente le cose.
- quando passi una reference "esponi" la tua variabile al rischo di
essere massacrata da uno sconosciuto. E' come quando passi un
puntatore: il tizio a cui lo passi puo' usarlo per cambiare il tuo
oggetto.
Personalmente infatti uso una "convenzione" che se ben ricordo e'
consigliata: passare SOLO references const, ovvero:
void non_stronka(const int& v)
{
  v = 75;  // BUM!! errore di compilazione!
}
Questo mi garantisce che nessuno possa "per errore" mettere le mani in
quello che gli passo, ma allo stesso tempo non faccio una copia.
Quando voglio autorizzare la funzione che chiamo a sfondare il mio
oggetto allora gli passo esplicitamente un puntatore, dichiarando
quindi:
void stronka_pura(int* v)
{
  *v = 75;
}
In questo modo quando chiamo la funzione DEVO farlo con:
  stronka_pure(&b);
e leggendo la chiamata, anche senza sapere come la funzione e'
dichiarata, "immagino" che possa sfondare la variabile b, visto che
vedo che gli sto passando il puntatore.
(nota tecnica: il passaggio per reference e' solitamente fatto
passando un puntatore, ma non e' necessario. Direi che nel caso di una
funzione inline a cui viene passata una const reference di fatto non
si passa proprio nulla a nessuno, con benefici risultati per i tempi
di esecuzione).
Sperando di non avere detto troppe balle....
Ciao,
Alberto
-- 
Alberto BARSELLA
PGP fingerprint = 13 3F 22 D2 0B 0A D3 25  F1 89 FE B5 82 AD 75 2A
** Beliefs are dangerous. Beliefs allow the mind to stop functioning.
A non-functioning mind is clinically dead.  Believe in nothing... **

nei tricks.
Proviamo a chiarire *cos'e` un reference*.
In un certo senso e` un semplice "alias" per una variabile.
int i = 0;
int& j=i;    // j e` SINONIMO di i
++i;    // incrementa i
++j;    // incrementa la STESSA variabile
Dopo questo frammento, i vale 2: infatti, partito eguale a zero, e` stato
incrementato due volte -- una volta col suo nome, un'altra con l'alias (aka
reference) j.
Chiaro fin qui, spero?  Se invece avessi avuto:
int j = i;    // *copia*, NON sinonimo!!!
j sarebbe PARTITO con una copia del valore di i (0 a quel punto), ma
poi rimanendo completamente *disaccoppiato* da i.  Dopo questo
frammento (quello sopra con questa sostituzione), i varrebbe 1.  OK
sin qui, spero?
Bene, per parametri di funzione, invece che variabili locali come in
questo esempio, e` *esattamente eguale*: passaggio per valore e`
copia una tantum; passaggio per reference e` temporanea creazione
di un ALIAS della variabile "passata"!
Quindi:
void noncambia(int i) {
    i=23;
}
void cambia(int& i) {
    i=34;
}
int i=12;
    cout<<i<<endl;
    noncambia(i);
    cout<<i<<endl;
    cambia(i);
    cout<<i<<endl;
cosa scrivera`?
Risposta...:
12
12
34
Infatti l'assegnamento i=23 in noncambia() e` ad una COPIA LOCALE
e non ha quindi alcun effetto sulla variabile "passata"; invece quello
i=34 in cambia() e` ad un ALIAS DELLA VARIABILE PASSATA, e
quindi in effetti CAMBIA quest'ultima...
Un po' piu` chiaro adesso...?  Facci sapere!
Alex

 Un po' piu` chiaro adesso...?  Facci sapere!
Eh, devo ammettere che... ho capito! E credo che questo non sia buono per te...
visto che di dubbi e domande ne ho un sacco e una gavetta e che questo
newsgroup è popolato di persone veramente disponibili,  anche a spiegare cose
basilari e banali (come lo era questa, credo)!Io mi impegno a formulare domande
più pregnanti e stuzzicanti, voi vi impegnate a rispondere, no?
E (forse) avrete sulla coscienza uno in più che sa programmare in C++.
per il momento non mi rimane che sperimentare.
Grazie e a presto.
P.S. Ho incominciato con C++Builder, penso sia molto comodo e che faccia
risparmiare molto tempo nella fase di apprendimento dell'IDE. Cosa ne pensi?
Avevo inizialmente pensato a djgpp che è aggratis, ma tirarlo giu` da internet
con il mio modemaccio 28k8...
Ciao
 Droide.


Mi sono perso... Cosa intendi per "...di fatto non si passa nulla a nessuno"? So
cosa sono (a grandi linee) le fun. inline. Tali funzioni vengono *espanse* (anche
se il termine è improprio) direttamente con codice alla loro chiamata, senza
attivare il classico meccanismo di chiamata a funzione, giusto? Poi, non ho
afferrato.
Avrei anche qualche domanda su come funzionano i costruttori di copia, ma a dire il
vero non ho ancora affrontato il tema, che temo sia piuttosto delicato. Verso la
fine di questa settimana magari mi rifaccio vivo.
Grazie.
Ciao
 Droide.

con il mio modemaccio 28k8...
Possibile che non si trovi su qualche CDROM, magari di quelli a basso
prezzo dati assieme a riviste...?  A proposito, attenzione: il GNUWIN32
sul CDROM oggi in edicola con ioProgrammo e` la versione *vecchia*,
maggio '97 -- sulla rete (*eccetto* che al mirror italiano, mannaggia...!)
c'e` invece la versione piu` recente.  (GNUWIN32, dispetto a DJGPP, e`
un altro port del compilatore GNU su PC, con la differenza che, "a
corredo", ha un discretamente completo ambiente di sviluppo Unix
like, sempre GNU, con shell BASH, tutti i comandini, eccetera; esso
supporta solo Win32, cioe` Windows 95, 98, e NT, non DOS nudo).
Ma succhiarsi 20mega o giu` di li` e` in effetti una prospettiva assai
poco allettante, sigh...
Alex

fine di questa settimana magari mi rifaccio vivo.
I copy ctor ("costruttori di copia") non sono affatto misteriosi come
funzionamento,
al massimo il problema puo` venire dal fatto che il compilatore ne inserisce
in ogni
posto dove una inizializzazione per copia venga fatta, tipo passaggio di
argomenti
e ritorno di valori come risultato di funzioni.  Comunque la cosa davvero
importante
e` capire la differenza (cruciale...!) fra copy ctor e assegnazione...!
Alex

Esiste un prg shareware Getright 3.1, sotto Win32, che permette di
downloadare file in più sessioni.
Io scarico decine di mega, senza mai avere alcun problema.
Il porting dello GNU fatto dalla Cygnus per win32, e' in un file
autoscompattante che puo presentare qualche problema: se vi dà degli errori
per mancanze di file, cercate sul vostro HD file con lo stesso nome e
copiateli nella directory di installazione, ricominciando nuovamente la
scompattazione.
A quanto pare si sono scordati qualche file d'installazione....
Iskandar ibn Nasser