Newsgroup: it.comp.lang.c++
Titolo: Restituzione di un riferimento....

Restituendo un riferimento, può essere chiamato direttamente sulla funzione
un metodo della classe il cui tipo è restituito, mentre restituendo per
valore no (devo assegnarlo ad un oggetto e poi chiamare il metodo su
quello).
Allora, come mai ad esempio, l'operatore + della classe string restituisce
per valore il  nuovo oggetto string derivato dalla concatenazione e non per
riferimento e riesco  a chiamare direttamente sul risultato ad esempio
size()?
Se fosse restituito effettivamente per valore, non dovrebbe essere possibile
fare:
string str1 ("Cip e "), str2("Ciop");
cout<<(a+b).size()<<endl;
no?
E' perchè viene usato comunque un oggetto interno, usando però
l'ottimizzazione per cui la chiamata a funzione (operator+) necessaria per
concatenare la string a e b (a+b) viene trasformasta in:
string c;
operator+( c, a, b );
?
Lo stesso succede anche col metodo to_string() della classe bitset() che col
metodo substr() della classe string?
Scusatemi per eventuali cretinate dette, ma non miriesco a spiegare perchè
nel prototipo di quelle funzioni c'è la restituzione per valore e non per
riferimento.
--
Marco Iannaccone
marc...@tin.it
ICQ UIN: 18748121     MetalCoder
"What is real? How do you define real? If you're talking about your senses,
what you feel, taste,
smell, or see, then all you're talking about are electrical signals
interpreted by your brain."
        Morpheus - The Matrix

 quello).
Mica vero!
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

 Mica vero!
Cioè possono fare qualcosa del tipo funzione()++ anche restituendo per
valore?. Almeno con i tipi primitivi non funziona...
Potresti farmi magari un esempio?


 Potresti farmi magari un esempio?
Ok, mi autopunisco per la STRONZATA che ho detto :-)
Praticamente, facendo una semplicissima prova, sono giunto alla conclusione
che quando restituisco per valore, ottengo un rvalue, su cui posso chiamare
in generale un metodo, ma che non posso usare per modificare il contenuto
dell'oggetto (con operatori come ++, o =, +=, etc...), mentre per
riferimento, restituendo un lvalue, posso farlo, stando comunque attendo a
fare in modo che il riferimento sia valido all'uscita della funzione...


 fare in modo che il riferimento sia valido all'uscita della funzione...
Da altre prove, però, ho notato che anche definendo un operator++(int) (++
postfisso), facendo una funzione che restituisce per valore un oggetto di
quella classe e facendo:
funz()++;
funziona perfettamente, mentre facendo lo stesso con una funzione che
restituisce un int il compilatore mi dice che non ho un lvalue come
parametro per l'operatore. Come mai? In questo caso ci mette lo zampino
quella ottimizzazione che dicevo 2 post fa, per caso, o cosa? Forse il
"divieto di modifica" restituendo per valore c'è solo con i primitivi?
(anche applicando l'operatore & alla funzione ottengo correttamente
l'indirizzo dell'oggeto restituito, anche se è ovviamente l'indirizzo della
copia, no?...) O è la mia definizione dell'operatore ++ interna alla classe
che fa si che non richieda un lvalue?


 che fa si che non richieda un lvalue?
No, il "divieto di modifica" vale anche per i tipi user defined, solo
che per questi l'operator++(int) diventa una chiamata a metodo come
tutte le altre ed il compilatore non fa distinzioni.
Ciao,
Nicola

 tutte le altre ed il compilatore non fa distinzioni.
Per cui qualsiasi chiamata ad un metodo, indipendentemente da quello che faa
è sempre possibile su un oggetto restituito per valore (quindi rvalue). C'è
invece qualche modo con cui potrei modoficare il valore non ricorrendo ad un
metodo, e che quindi mi verrebbe impedito col messaggio "non-lvalue...."?(mi
sa di no, comunque...)
--
Marco Iannaccone
marc...@tin.it
ICQ UIN: 18748121     MetalCoder
"I bei film drammatici fanno sentire intelligenti anche gli stupidi, i bei
film comici fanno tornare bambini anche le persone intelligenti.
Peccato che sia più facile trovare stupidi che vogliono sembrare
intelligenti che persone intelligenti col coraggio di saper tornare bambini"
        Stan Laurel

Ovviamente non esistono operatori *predefiniti* su tipi definiti
dall'utente...
Ciao,
Nicola

 dall'utente...
Ok, perfetto. In conclusione, sui tipi user-defined funzionano le modifiche
tramite operatori come ++ o += anche se restituiti per valore, mentre sui
predefiniti no :-)


 sa di no, comunque...)
Ti dico la mia.
Non so nulla del "divieto di modifica" citato da Nicola. Ma so che lo standard
dice che un lvalue fa riferimento ad un oggetto o una funzione mentre un rvalue
normalmente non fa riferimento ad un oggetto *a meno che* non sia un rvalue di
classe. In questo caso anche se e' un rvalue fa comunque riferimento ad un
oggetto.
In specifico puoi chiamare un metodo di un oggetto anche partendo da un
riferimento ad esso che e' un rvalue. Non serve che sia un lvalue. Il metodo non
deve necessariamente avere il this costante. Pertanto l'oggetto puo' essere
modificato.
Ergo se definisci un metodo (esempio l'operator++) questo puo' essere chiamato.
Nota pero' che la cosa dovrebbe essere diversa se, per esempio, definisci
l'operator++ esternamente alla classe (ovvero non come un suo metodo). In tal
caso non dovrebbe essere chiamabile perche' il suo (primo) parametro e' una
reference non costante e pertanto non "bindabile" con un rvalue. Ovviamente se
il compilatore e' conforme e se non mi e' sfuggito qualche cosa!


 ha scritto nel messaggio
news:3ACB30AD...@divalsim.it...

E operator= ed operator&?.
Considera questo esempio:
#include <string>
#include <iostream>
int main()
{
   std::string a = "a";
   std::string b = "b";
   std::cout << &(a + b) << '\n';
   std::cout << ((a + b) = a) << '\n';
}
Il programma dovrebbe compilare secondo lo Standard?
Saluti  Manlio Perillo

 Il programma dovrebbe compilare secondo lo Standard?
Non sono sicuro se non sia accettabile invocare l'operatore & su un
temporaneo di tipo user defined.
Ciao,
Nicola
P.S. Ben tornato! Sei in licenza?

 P.S. Ben tornato! Sei in licenza?
Si (e purtroppo è anche già finita, al mese prossimo...).
Manlio Perillo

 ho trovato nulla a riguardo.
Vedi 5.3.1. 2 . L'operatore & e' predefinito per tutti i tipi (e'
ragionevole, poiche' non richiede di essere sintetizzato per ciascuna
classe). Se ne esiste uno definito dall'utente si prende quello,
altrimenti si ricade su quello predefinito.
 
Ciao,
Nicola

 > temporaneo di tipo user defined.
Dipende se e' o meno un lvalue. Indipendentemente dal fatto che si tratti o meno
di un user defined. Salvo il solito caso di operator& come membro!
--
