Newsgroup: it.comp.lang.c++
Titolo: Funz. operatore che ritorna un reference

Ho questa funzione di overload di operatore:
////////////////////////////////////////////////////
// Array è una classe per creare, gestire vettori:
class Array {
//...
public:
const int &Array::operator[] ( int subscript ) const
{
    return ptr[ subscript ];
}
private:
     int *ptr; // points to the first element of array
};
////////////////////////////////////////////////////
Non arrivo a capire una cosa.
Per me ptr[subscript] dovrebbe essere un intero, perché allora la 
funzione non è:
const int Array::operator[] ( int subscript ) const
???
Grazie

 Per me ptr[subscript] dovrebbe essere un intero
No, un reference ad intero. Se fosse solo un intero, non otterresti un
l-value e non potresti quindi assegnare un valore tramite subscript. E
comunque devi togliere quel const.

nembo kid ha scritto:

In questo caso (siccome la funzione è const) in effetti la versione che 
ritorna il valore è equivalente a quella che ritorna il riferimento.
Anzi, potrebbe anche essere un pelino più efficiente siccome l'int è 
piccolo (ma probabilmente con un buon compilatore non cambia nulla).
Un motivo per mantenere il ritorno col reference, può essere quello di 
"omogeneità" con la versione non cost, che nell'esempio che hai messo tu 
non c'è ma in generale (a meno ché il concetto di "Array" che vuoi 
esprimere sia immutabile) è presente:
const int &Array::operator[] ( int subscript ) const
{
  return ptr[ subscript ];
}
int &Array::operator[] ( int subscript )
{
  return ptr[ subscript ];
}
E nota bene che la versione non const (come ti è già stato fatto notare) 
DEVE tornare un reference per poter essere l-value (cioè poter stare a 
sx di un assegnamento)
Occhio che se invece che int l'array fosse di roba più grossa (o ad 
esempio di un tipo T generico argomento di template) la versione col 
reference sarebbe anche + efficiente (si risparmia la copia).
GM

 sx di un assegnamento)
Infatti, il Deitel le mette due const e non const, rispettivamente per 
creare un rvalue e un lvalue.


E' preferibile cosi', perche' e' sempre meglio evitare di ritornare
reference (cosi' come ritornare puntatori) quando si puo'.
Tra l'altro la "promessa" che si fa ritornando un reference e'
decisamente piu' forte di quella che si fa ritornando un puntatore;
mentre i puntatori per definizione possono essere validi, nulli o non
validi, i reference si assume che siano sempre validi. Ritornando un
reference quindi in un certo qual modo ti impegni a mantenere valido
l'oggetto riferito a tempo indeterminato.
Ciao,
Nicola

 l'oggetto riferito a tempo indeterminato.
Questo no. Da questo punto di vista non vedo differenza con un 
puntatore. Anche se ritorni un puntatore non è bello se l'oggetto 
puntato diventa improvvisamente non valido.
Ma ha poi senso pensare questo? La stringa ha la funzione c_str() che 
torna un puntatore costante, ma non rende di certo la stringa 
immutabile, e quindi il puntatore "sempre" valido. L'operatore [], o di 
assegnazione è ragionevole che torni un reference, ma è anche 
ragionevole che non _fissi_ l'oggetto referenziato.
Se poi uno ci tiene a cercarsi rogne a tutti i costi, allora il C++ è 
il linguaggio che fa per lui:
std::vector<std::string> vect;
vect.push_back("Hello");
vect.push_back("Duck");
size_t i = vect.size();
while(i--)
{
 const std::string& s = vect[i];
 vect.pop_back();
 const char * p = s.c_str();
  // per motivi ignoti a me con vc2005 ho che p == 0
}
-- 
Articolo 33 della Costituzione italiana: L'arte e la scienza sono 
libere e libero ne è l'insegnamento.
detto qesto: 
http://www.pluto.it/files/ildp/HOWTO/Coffee/Coffee.html
oppure questo? 
http://lenr-canr.org/acrobat/DeNinnoAexperiment.pdf

 }
Vien da pensare che il distruttore di std::string, scatenato dalla
chiamata a pop_back(), riporti l'oggetto ad uno stato iniziale valido.
Si comporta allo stesso modo se compili in modo debug o in release? VC+
+2005 ha anche il controllo sullo sfondamento dei buffer se non
ricordo male, mi sembrava ci fosse qualche macro da definire per
abilitarlo/disabilitarlo.
Ciao,
Nicola

 abilitarlo/disabilitarlo.
L'ho disabilitato, ma il risultato non è cambiato.


Lo dico tanto per precisare,
l-value non significa strettamente "poter stare a sinistra di un 
assegnamento"
era originariamente così ... lo standard indica l-value come "localtion 
value"
ovvero un espressione con la quale è possibile riferirsi ad un oggetto ...
lo dico per i nuovi di questo linguaggio che prendono per buono tutto quello
che viene detto :-)
by.
