Newsgroup: it.comp.lang.c++
Titolo: return

ho ho avuto necessita di fare una funzione che restituisce 2 valori interi,
ora come faccio ad associarli a 2 variabiliquando richiamo la funzione?
pippo
{
....
....
return(a,b)
}
main
{
...
...
?=pippo() //  <-------?
}
grazie

 }
void pippo(int & a, int & b)            // "int" e' un esempio;
{ ... a = 1; ... b = 2; ... }           //   cosi' come i valori assegnati.
-- 
Maurizio Loreti  - Linux Is Not UniX -  
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 funzione?
struct pippo_struct { int a; int b; };
pippo_struct pippo(int n) {
 pippo_struct res;
 res.a = n;
 res.b = n << 2;
 return res;
}
int main() {
 pippo_struct result = pippo(1);
}

 }
Non č possibile far ritornare piů di un valore ad una funzione: quello che
hai scritto č corretto per il semplice fatto che l'espressione:
(a, b)
ha come risultato b; piů in generale, raggruppando insieme vari statement
tra due () e separandole da virgole, il risultato dell'espressione č dato
dall'ultimo statement a destra:
int a=10, *b=&a;
char c;
string s;
int d=(a=20, c='a', s="ciao", *b);
L'ultima linea equivale ad assegnare all'intero d il valore puntato da b.
Tornando al tuo esempio, la funzione pippo() ha come unico valore di ritorno
b.
Ciao,
Cecco

 ha scritto nel messaggio
news:%IN88.39922$nI1.1...@twister1.libero.it...

#include <iostream>
#include <utility>
typedef std::pair<int, int> Doppio_int;
Doppio_int pippo(int a, int b)
{
    return Doppio_int(a, b);
}
int main()
{
    Doppio_int r = pippo(3, 5);
    std::cout << "primo int = " << r.first << std::endl;
    std::cout << "secondo int = " << r.second << std::endl;
}
Questa è a mio avviso la soluzione migliore, perché utilizza solo componenti
standard e non implica la creazione di nuove strutture o meccanismi
artificiosi per restituire i valori.
Marco

{ ... a = 1; ... b = 2; ... }           //   cosi' come i valori assegnati.
Lo Stroustrup depreca e sconsiglia di usare references non const come
parametri di funzioni, in quanto impedisce di capire con chiarezza a
chi chiama la funzione che i parametri potrebbero esseri modificati
dalla funzione stessa.
Se abbia o meno ragione non lo so(tale tecnica l'ho usata diverse
volte e mi sto chiedendo tuttora se sia ragionevole continuare ad
usarla in futuro) ma l'uso di puntatori forse rende più chiara la
volontà della funzione di modificare i parametri.
Il Ghenio
---------
// TODO: Place your ass here


BS ne sa certamente piu' di me, pero' l'utilizzo di puntatori ti impone
di prendere in considerazione la possibilita' che ti vengano passati
puntatori nulli, mentre coi reference specifichi a chi usa la tua
funzione che *deve* passare argomenti validi.
Ciao,
Nicola

 dalla funzione stessa.
D'oh!  Proporro' un amendment allo Standard che abolisca
std::swap     :-) :-) :-)


 artificiosi per restituire i valori.
Oppure, nel caso si volessero restituire piů di due valori si puň restituire
un <vector>
--
Gerolamo

 funzione che *deve* passare argomenti validi.
Non è detto che un puntatore nullo sia di per se invalido... anche il 
valore NULL (o se preferite 0) può avere un suo 'significato'.
-- 
Luc.


Per l'appunto. Proprio per questo non trovo giustificabile scegliere se
passare i parametri per puntatore o per reference solo per una questione
di presunta leggibilita'.
Ciao,
Nicola

 dalla funzione stessa.
Dove hai trovato questo punto di vista? Per coincidenza ho appena letto
il paragrafo 7.2 "Argument Passing" di TC++PL3 e non ne fa menzione.
Ciao,
Nicola

il paragrafo 7.2 "Argument Passing" di TC++PL3 e non ne fa menzione.
Premetto che ho l'edizione italiana "C++, linguaggio,libreria
standard,principi di programmazione" del 2000, e tale punto di vista
viene affermato in più occasioni. Te ne riporto alcune che ho
trovato...
Capitolo 5.5: riferimenti.
pag.112/113
[....]
void increment(int& aa) {aa++;}
int next(int p) {return p++;}
void incr(int* p) { (*p)++; }
La notazione increment(x) non da nessun indizio a chi esamina il
codice sul fatto che x sarà modificata dalla funzione. Invece ciò
risulta chiaro dalle scritture x=next(x) e solo incr(&x). Per questo
motivo l'uso di argomenti riferimenti "puri" dovrebbe essere usato
solo nel caso in cui il nome della funzione dia chiaramente l'idea
della modifica.
[....]
suggerimenti di fine capitolo.
- Si minimizzi l'uso di argomenti riferimento puri.
Capitolo 7.2: Passaggio dei parametri.
void f(int val,int& ref)
{
val++;
ref++;
}
[....] Come si é detto in 5.5 , funzioni che modificano argomenti
passati per indirizzo possono risultare di difficile lettura e
dovrebbero essere evitate.[....]
suggerimenti di fine capitolo.
- Si guardi con sospetto ad argomenti riferimento non const. Se si
vuole che una funzione modifichi i propri argomenti SI USINO PUNTATORI
E VALORI DI RITORNO.
[....]


funzione che *deve* passare argomenti validi.
A mio avviso non cambia molto per chi deve scrivere una funzione,e
controllare che i puntatori passati non siano nulli é una cosa che
spesso può essere evitata(a meno che il puntatore nullo non abbia un
significato ben preciso), anche perché imporrebbe di lanciare
eccezioni o tornare codici di errore, e sicuramente diventa molto più
semplice anche per il chiamante controllare cosa sta passando alla
funzione piuttosto che gestire tali situazioni.


 il paragrafo 7.2 "Argument Passing" di TC++PL3 e non ne fa menzione.
nella mia edizione in 7.2 a pagina 146 si dice:
"as mentioned in 5.5, functions that modify call-by-reference
arguments can make programs hard to read and should most often
be avoided (but see 21.2.1)"
Andrea


Ma lo scope di res non è limitato alla funzione pippo? Non dovrebbe essere
scorretto restituirlo al chiamante?
Chiedo perché non sono sicuro nemmeno io di quello che dico e vorrei
conferme... grazie.

 scorretto restituirlo al chiamante?
Infatti non viene restituito res, bensě una sua copia (generata
automaticamente).
Se avesse scritto:
pippo_struct& pippo(int) {
    ...
    return res;
}
oppure
pippo_struct* pippo(int) {
    ...
    return &res;
}
allora sarebbe stato scorretto perché avrebbe restituito un riferimento alla
variabile res che, ovviamente, non esiste piů una volta usciti dalla
funzione.
    Marco

Visto, grazie. Ma a rischio di passare per eretico, continuo a non
condividere. Forse benche' non programmi piu' in Pascal da una
quindicina di anni mi sono rimasti in testa i parametri "var", che
corrispondono al passaggio per reference.
Ciao,
Nicola

 funzione piuttosto che gestire tali situazioni.
Spostandoci nel mondo del fanta-C++ mi domando se oggi come oggi non
converrebbe far fare il controllo dal runtime di default. Il compilatore
potrebbe eliminarlo in fase di ottimizzazione del codice e si potrebbe
permettere la disabilitazione esplicita via pragma o simili in porzioni
del codice dove il compilatore non riesce ad ottimizzare.
Ciao,
Nicola

condividere.
Nemmeno io condivido in pieno, anche perché aldilà delle presunte
ragioni di leggibilità non ci sono altri motivi per usare puntatori al
posto di references come parametri di funzioni, ma visto che si tratta
dell'opinione di una persona molto autorevole in materia di C++ mi
premeva sottolinearla.


del codice dove il compilatore non riesce ad ottimizzare.
Non mi convince molto... cosa succederebbe se un programma facesse di
tale controllo un punto fermo per garantire il suo funzionamento?
Il programma non potrebbe essere più ottimizzato causa il rischio di
non funzionare più(in pratica é ciò che succede già su alcuni sistemi
di sviluppo come il VB dove togliere alcuni controlli di sicurezza per
ottimizzare le prestazioni é molto rischioso e va fatto solo se si
conosce bene il funzionamente del programma), molto meglio secondo me
utilizzare la compilazione condizionale.



Non intendevo un'opzione generale di compilazione, bensi una direttiva
localizzata, che imponesse di disabilitare un singolo controllo, oppure
quelli contenuti nello stesso scope.
Il problema e' da una parte semplificare la vita al compilatore, in modo
che possa effettivamente ottimizzare ogni volta che e' sicuro, ma
consentire comunque al programmatore di intervenire in modo puntuale.
Ciao,
Nicola

Nicola Musatti wrote:

sono d'accordo con te (caso strano, anche io vengo dal pascal :-); anzi, 
spesso trovo che i reference sono piu` leggibili dei puntatori; volete 
mettere:
        void swap(int&, int&)
con
        void swap(int*, int*)
??
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

         void swap(int*, int*)
In effetti la presunta maggior evidenza del passare via puntatore i
parametri modificabili e' un illusione: una chiamata come
int i = 2;
int j = 3;
f(&i,&j);
operera' per valore sul puntatore o per riferimento sull'oggetto
puntato? Nemmeno la signature della funzione e' sufficiente per chiarire
il dubbio. Questa ambiguita' passando per reference non esiste.
Ciao,
Nicola