Newsgroup: it.comp.lang.c++
Titolo: Ritorno per riferimento

Potreste spiegarmi come si fa a ritornare un valore da una funzione per
riferimento?
Ciao
Stefano

 riferimento?
Sarei tentato di non spiegartelo, perche' e' spesso una pratica
discutibile, comunque:
int & f() {
  static i = 5;
  return i;
}
int j = f();  // j prende il valore di i...
j = 6;        // ... infatti qui i non cambia
int & k = f() // k prende l'indirizzo di i...
k = 7;        // ...e qui cambia anche i
Ciao,
Nicola

discutibile, comunque:
però è usato con molto profitto negli operator= e operator<<
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

 però è usato con molto profitto negli operator= e operator<<
Mettiamola cosi': e' discutibile tranne che in due casi:
1) ritorna "*this" da un metodo non statico.
2) ritorna un reference a un membro statico privato o a una statica della
funzione stessa nell'implementazione di un singleton o di una sua variante.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

funzione stessa nell'implementazione di un singleton o di una sua variante.
3) ritorna un const T& di un membro privato che si vuole rendere
accessibile solo in lettura, ma la cui copia è costosa
Anto


 accessibile solo in lettura, ma la cui copia è costosa
Questo e' l'uso rischioso, perche' chi chiama potrebbe memorizzare il
reference e  tentare di utilizzarlo quando non e' piu' valido.
Ciao,
Nicola

 accessibile solo in lettura, ma la cui copia è costosa
La contrario. La cosa e' fattibile e viene fatto spesso. Ma e' tremendamente
rischioso. Devi assicurarti che la reference sia "distrutta" prima che lo sia
l'oggetto. Per farlo hai due modi:
1) un qualche meccanismo di garbage collector nativo all'implementazione del
linguaggio (il che vuole dire che non e' piu' C++)
2) non ritorni una vera reference ma una "smart reference" (stessa famiglia
degli smart pointer) e l'oggetto gestisce un reference count.
In pratica quello che suggerisci e' esattamente quello che si stava consigliando
di evitare.


reference e  tentare di utilizzarlo quando non e' piu' valido.
vabbè, ma a questo punto è il chiamante a sbagliare, e se il metodo è
inline non ci sono problemi di efficienza. Cmq questo argomento mi
interessa: come si potrebbe fare in questo caso senza utilizzare i
reference?


 reference?
Con gli smart reference, ma ovviamente con problemi di efficienza. Oppure non in
C++. Questo e' uno dei vantaggi dei linguaggi con garbage collection.
Nota che anche se il meccanismo e' rischioso non significa che non e' usato o e'
da criticare. Solo che e' rischioso e bisogna saperlo.
Questo e' un esempio degli argomenti di critica verso il linguaggio: quello che
fai e' rischioso, ma non per motivi legati al tuo codice, semplicemente per come
e' fatto il linguaggio. Se come programmatore C++ cadi in un argomento come
questo in un circolo di programmazione smalltalk, ti guadagni qualche
compassionevole pacca sulle spalle.


 reference?
I modi fondamentali sono due, ciascuno dei quali puo' essere
implementato secondo diverse alternative:
- Per valore, se ha senso per la classe in questione, adottando
eventualmente
  meccanismi di copy-on-write o simili per evitare problemi di
prestazioni.
- Tramite puntatore, o meglio via smart pointer, in modo che sia chiaro
che
  il possesso dell'oggetto puntato e' mantenuto da qualcun altro.
Ciao,
Nicola

l'oggetto. Per farlo hai due modi:
personalmente mi sembra contrario alla filosofia del C++, ovvero rendi
facile la vita all'utente, ma se vuole complicarsela lo faccia pure:
seguendo il tuo ragionamendo allora togliamo anche i puntatori, visto
che possono puntare a qualcosa di insesistente. E poi quali sono le
alternative (domanda NON retorica)? Ti faccio un esempio stupido:
template<class T> class ReadOnly {
  T v;
public:
  ReadOnly(T vv): v(vv) { }
  const T& get() { return v; }
};
Come faccio a fare una cosa del genere senza ritornare un reference e
senza perdere in efficienza?
Se ho ben capito tu dici che il pericolo sarebbe questo:
ReadOnly<int> *r= new ReadOnly<int>(4);
const int& ref=r->get();
delete r;
// pericolo! esiste ancora ref!
però non ci vedo grande differenza con questo:
int* p= new int(4);
int& ref=*p;
delete r;
per la serie "se uno si vuole fare del male faccia pure..."


 per la serie "se uno si vuole fare del male faccia pure..."
Filosofia. Se parti dal presupposto che "se uno si vuole fare del male faccia
pure..." allora non puoi piu' paragonare Unix/Linux o anche solo Xenix a Windows
sulla base della protezione fra processi. Devi presumere che programmatori e
utenti siano abbastanza smart da non farsi del male. Ergo il sistema operativo
migliore del mondo e' DOS con un extender e un minimo di multitasking!
La realtà e' che non e' praticamente pensabile scrivere (con successo) codice
complesso e di grandi dimensioni per il quale e' assolutamente necessario che
non ci siano bachi (ad un livello parecchi ordini di magnitudine sopra alla
media) in C++. Pensa all'avionica di un velivolo militare (compresi i sistemi di
gestione delle info tattiche e di puntamento d'arma etc.) o ai SW di gestione di
centrali nucleari o di sistemi satellitari (compresi i SW di terra, non solo
quelli di volo). O al SW di controllo della navigazione aerea di un aereoporto.
Non per nulla sono tutti sviluppati in ADA o in Smalltalk (il secondo per
sistemi di terra, leggermente meno critici dal punto di vista deterministico per
cui e' accetabile la garbage collection).
Ti sembrera' strano ma avrebbe piu' senso usare Java (non in volo, vedi
determinismo) che non C++ in questi casi.
Pertanto alla tua domanda "quali alternative" la risposta e': niente reference e
niente puntatori. Persino niente istanze non dinamiche. Solo ed esclusivamente
smartpointer. Sia nelle variabili locali, che come parametri, che come valori di
ritorno, che come membri.
Ovvio che stiamo snaturando completamente il C++. Ma questo e' l'estremo
opposto. Quale sia la linea di demarcazione dipende da te e dall'applicazione
che stai sviluppando. Decidere quale e' il bilancio di convenienza fra
efficienza, rischio, sicurezza, correttezza, tempo di sviluppo etc. etc.
ovviamente e' il tuo lavoro. Ancora piu' che non lo scrivere il codice. Almeno
in teoria.


cavolo, ma è possibile che in una discussione con te non riesca mai ad
avere l'ultima parola??? ;-)
grazie mille!
