Restituire più valori da una funzione di C++

C’è un modo preferito per restituire più valori da una funzione C++? Per esempio, immaginate una funzione che divide i due numeri interi e restituisce il quoziente e il resto. Un modo comunemente vedere è quello di utilizzare i parametri di riferimento:

void divide(int dividend, int divisor, int& quotient, int& remainder);

Una variante è quello di restituire un valore e passare attraverso un parametro di riferimento:

int divide(int dividend, int divisor, int& remainder);

Un altro modo sarebbe quello di dichiarare una struttura per contenere tutti i risultati e ritorno:

struct divide_result {
    int quotient;
    int remainder;
};

divide_result divide(int dividend, int divisor);

È uno di questi modi è generalmente preferita, o ci sono altri suggerimenti?

Edit: Nel codice reale, ci possono essere più di due risultati. Essi possono anche essere di diversi tipi.

InformationsquelleAutor Fred Larson | 2008-11-26



20 Replies
  1. 184

    Per la restituzione di due valori io uso un std::pair (di solito typedef d). Si dovrebbe guardare boost::tuple (in C++11 e più recenti, c’è std::tuple) per più di due restituire i risultati.

    Con l’introduzione di un processo strutturato di associazione in C++ 17, tornando std::tuple probabilmente dovrebbe diventare standard accettato.

    • +1 per la tupla. Tenete a mente le prestazioni ramificazioni di oggetti di grandi dimensioni di ritorno in una struttura contro il passaggio per riferimento.
    • Se avete intenzione di utilizzare le tuple, perché non utilizzarli per coppie. Perché sono un caso particolare?
    • Può boost::tupla di gestire diversi tipi nella stessa tupla? Forse si può usare boost::qualsiasi con esso.
    • Fred, sì boost::tupla può fare 🙂
    • E ‘stato un po’, ma credo di accettare questa risposta come il favorito della folla.
    • In C++11, è possibile utilizzare std::tuple.
    • Ferruccio: Boost non è esattamente una leggera dipendenza. Se il vostro progetto non dipende di sicurezza, boost::tuple per più valori di ritorno non è esattamente un buon caso per il trascinamento di Spinta. (Questo detto da chi ha trascorso molte ore a giocherellare con il Boost peculiarità di Windows e AIX; quello che appare come un “sempre lì” dipendenza su Linux è una fonte di forti mal di testa altrove. Lo uso, ma essere consapevoli di esso.)
    • Se si desidera accettare più valori da una funzione, un modo pratico per farlo è quello di utilizzare std::tie stackoverflow.com/a/2573822/502144
    • Io preferisco le strutture in generale, ma le tuple sono impressionanti a causa di std::tie(var_a, var_b) = func_returning_tuple();
    • essi sono anche più impressionante in C++17: auto &[a, b] = func();

  2. 140

    In C++11 è possibile:

    #include <tuple>
    
    std::tuple<int, int> divide(int dividend, int divisor) {
        return  std::make_tuple(dividend / divisor, dividend % divisor);
    }
    
    #include <iostream>
    
    int main() {
        using namespace std;
    
        int quotient, remainder;
    
        tie(quotient, remainder) = divide(14, 3);
    
        cout << quotient << ',' << remainder << endl;
    }

    In C++17:

    #include <tuple>
    
    std::tuple<int, int> divide(int dividend, int divisor) {
        return  {dividend / divisor, dividend % divisor};
    }
    
    #include <iostream>
    
    int main() {
        using namespace std;
    
        auto [quotient, remainder] = divide(14, 3);
    
        cout << quotient << ',' << remainder << endl;
    }

    o con le strutture:

    auto divide(int dividend, int divisor) {
        struct result {int quotient; int remainder;};
        return result {dividend / divisor, dividend % divisor};
    }
    
    #include <iostream>
    
    int main() {
        using namespace std;
    
        auto result = divide(14, 3);
    
        cout << result.quotient << ',' << result.remainder << endl;
    
        //or
    
        auto [quotient, remainder] = divide(14, 3);
    
        cout << quotient << ',' << remainder << endl;
    }
    • Ho una preoccupazione con funzioni di restituzione di tuple. Dire che la funzione di cui sopra prototipo è l’intestazione, quindi come faccio a sapere che cosa fa il primo e il secondo valori restituiti dire senza conoscere la definizione di funzione ? quoziente-resto o resto-quoziente.
    • Stessa preoccupazione per i parametri della funzione, è possibile dare nomi a loro, ma il linguaggio non imporre, e i nomi dei parametri, non hanno alcun valore al sito di chiamata durante la lettura. Inoltre, su un single di ritorno, è solo un tipo, ma avendo il nome potrebbe anche essere utile, con tuple basta fare doppio il problema, quindi, imo, la lingua appena manca per quanto riguarda l’essere auto-documentati in diversi modi, non solo per questo.
    • come ultimo esempio, se ho voluto esplicitamente specificare il tipo di ritorno di divisione()? Devo definire il risultato da qualche altra parte, o sono in grado di definire, proprio nel tipo di ritorno specifica?
    • non si può definire un tipo a destra la firma della funzione, è necessario dichiarare il tipo al di fuori e usarlo come tipo di ritorno, come è normalmente fatto (basta spostare il struct linea al di fuori del corpo della funzione e sostituire auto funzione di ritorno con result.
    • Se vuoi mettere la definizione di funzione di divide in un file cpp? Ottengo l’errore error: use of ‘auto divide(int, int)’ before deduction of ‘auto’. Come posso risolvere questo?
    • lo risolvi come spiego nel mio commento precedente. Si può avere di prototipi con auto ritorno in intestazioni, il tipo di ritorno deve essere dedotto dal codice.
    • Nel primo esempio si può utilizzare auto divide(int dividend, int divisor) { return std::pair{dividend / divisor, dividend % divisor}; }

  3. 118

    Personalmente, io in genere antipatia di ritorno parametri per una serie di motivi:

    • non è sempre evidente nell’invocazione che i parametri di ins e che sono out
    • in genere necessario creare una variabile locale per prendere il risultato, mentre i valori di ritorno possono essere utilizzati in linea (che può o non può essere una buona idea, ma almeno hai l’opzione)
    • sembra pulitore a me di avere un “porta a porta” e un “fuori porta” di una funzione-tutti gli ingressi di andare qui, tutte le uscite di venire fuori
    • Mi piace tenere i miei elenchi di argomenti più breve possibile

    Ho anche alcune riserve circa la coppia/tupla tecnica. Soprattutto, spesso non c’è l’ordine naturale, per i valori di ritorno. Come è il lettore di codice a sapere se il risultato.il primo è il quoziente o il resto? E il realizzatore potrebbero modificare l’ordine, che potrebbe rompere il codice esistente. Questo è particolarmente insidioso se i valori sono dello stesso tipo, in modo che nessun errore di compilazione o di avviso sarebbe generato. In realtà, questi argomenti sono validi per tornare parametri.

    Ecco un altro esempio di codice, questo un po ‘ meno banale:

    pair<double,double> calculateResultingVelocity(double windSpeed, double windAzimuth,
                                                   double planeAirspeed, double planeCourse);
    
    pair<double,double> result = calculateResultingVelocity(25, 320, 280, 90);
    cout << result.first << endl;
    cout << result.second << endl;

    Fa stampare la velocità al suolo e corso, o del corso e la velocità al suolo? Non è ovvio.

    Paragonare a questo:

    struct Velocity {
        double speed;
        double azimuth;
    };
    Velocity calculateResultingVelocity(double windSpeed, double windAzimuth,
                                        double planeAirspeed, double planeCourse);
    
    Velocity result = calculateResultingVelocity(25, 320, 280, 90);
    cout << result.speed << endl;
    cout << result.azimuth << endl;

    Penso che questo è più chiaro.

    Quindi penso che la mia prima scelta, in generale, è la struttura tecnica. La coppia/tupla idea è probabilmente una grande soluzione in certi casi. Vorrei evitare il ritorno parametri, quando possibile.

    • La proposta di dichiarare una struct come Velocity è un bel uno. Tuttavia, una preoccupazione è che inquina lo spazio dei nomi. Suppongo che con C++11, il struct può avere una lunga digitare il nome e si può utilizzare auto result = calculateResultingVelocity(...).
    • +1. Una funzione deve restituire il uno “cosa”, non in qualche modo ordinato “tupla di cose”.
    • Io preferisco le strutture oltre std::coppie/std::tuple per i motivi descritti in questa risposta. Ma non mi piace lo spazio dei nomi “inquinamento” anche. La soluzione ideale per me sarebbe la trasformazione in forma anonima struct come struct { int a, b; } my_func();. Questo potrebbe essere utilizzato come questa: auto result = my_func();. Ma C++ non permettere questo: “nuove tipologie non può essere definito in un tipo di ritorno”. Quindi devo creare strutture come struct my_func_result_t
    • C++14 permette il ritorno tipi locali con auto, così auto result = my_func(); è facilmente ottenibile.
    • Sembra che funzioni: coliru.stacked-crooked.com/a/2a80e1007ff8804e . Ma il corpo della funzione deve essere definita nel file di intestazione.
    • Circa 15 anni fa, quando abbiamo scoperto boost abbiamo usato tupla molto dal momento che è abbastanza a portata di mano. Ore di lavoro straordinario che abbiamo vissuto lo svantaggio in leggibilità, soprattutto per le tuple di avere lo stesso tipo (ad esempio tupla<double, double>; che uno è che). Così ultimamente ci sono più l’abitudine di introdurre un piccolo CONTENITORE struttura in cui almeno il nome della variabile membro indica qualcosa di sensato.

  4. 22
    std::pair<int, int> divide(int dividend, int divisor)
    {
       //:
       return std::make_pair(quotient, remainder);
    }
    
    std::pair<int, int> answer = divide(5,2);
     //answer.first == quotient
     //answer.second == remainder

    std::pair è essenzialmente il vostro struct soluzione, ma già definiti, e pronto ad adattarsi a qualsiasi due tipi di dati.

    • Che lavorerà per il mio semplice esempio. In generale, tuttavia, ci possono essere più di due valori restituiti.
    • Inoltre, non è autoesplicativo. Si può ricordare che registro x86 è il resto per il DIV?
    • Sono d’accordo che posizionali, le soluzioni possono essere mantenibile. È possibile eseguire il “permute e deflettore” problema.
  5. 15

    È interamente dipendente, al momento dell’effettiva funzione e il significato dei valori, e le loro dimensioni:

    • Se essi sono correlati come nella frazione di esempio, quindi mi piacerebbe andare con una struttura o un’istanza della classe.
    • Se non sono molto legate e non possono essere raggruppati in una classe/struct allora forse si dovrebbe effettuare il refactoring del metodo in due.
    • A seconda della dimensione di in memoria dei valori di ritorno, se si desidera restituire un puntatore a un’istanza di classe o di una struttura, o di utilizzare i parametri di riferimento.
  6. 12

    OO soluzione per questo è di creare un rapporto di classe. Non prendere alcun codice aggiuntivo (vorrei risparmiare un po), sarebbe più pulito/più chiaro, e vi darà qualche extra in rifattorizzazione consentendo di pulizia codice al di fuori di questa classe.

    In realtà penso che qualcuno consiglia la restituzione di una struttura, che è abbastanza vicino, ma nasconde l’intento che questo deve essere un pensiero-fuori classe con un costruttore e un paio di metodi, infatti, il “metodo” che è stato originariamente indicati (come restituire la coppia) dovrebbe probabilmente essere un membro di questa classe di restituire un’istanza di se stesso.

    So che il tuo esempio era solo un “Esempio”, ma il fatto è che a meno che la funzione è di fare molto più di qualsiasi funzione che dovrebbe fare, se si desidera restituire più valori sono quasi certamente manca un oggetto.

    Non abbiate paura di creare queste piccole classi per fare un po ‘ di lavoro … è la magia di OO–si finisce per rompere giù fino a quando ogni metodo è molto piccolo e semplice, e in ogni classe piccola e comprensibile.

    Un’altra cosa che dovrebbe essere un indicatore che qualcosa era sbagliato: OO si sono essenzialmente dati–OO non è sul passaggio di dati, una classe deve gestire i propri dati internamente, ogni passaggio di dati (comprese le funzioni di accesso) è un segno che potrebbe essere necessario ripensare qualcosa..

  7. 10

    C’è un precedente per il ritorno di strutture in C (e, quindi, C++) standard con il div, ldiv (e, in C99, lldiv) funzioni da <stdlib.h> (o <cstdlib>).

    Il ‘mix di restituire valore e il ritorno dei parametri di solito è meno pulito.

    Avere una funzione di restituire lo stato e restituire i dati via ritorno parametri è sensato C; è meno ovviamente sensato in C++ per cui si possono usare le eccezioni per l’inoltro di informazioni di errore invece.

    Se ci sono più di due valori di ritorno, quindi una struttura simile meccanismo è probabilmente il migliore.

  8. 10

    Con C++17 si può anche restituire uno o più immobili/duplicabile valori (in alcuni casi). La possibilità di restituire inamovibile tipi di venire via il nuovo garantito il valore di ritorno di ottimizzazione, e si compone perfettamente con aggregati, e quello che può essere chiamato basato su modelli costruttori.

    template<typename T1,typename T2,typename T3>
    struct many {
      T1 a;
      T2 b;
      T3 c;
    };
    
    //guide:
    template<class T1, class T2, class T3>
    many(T1, T2, T3) -> many<T1, T2, T3>;
    
    auto f(){ return many{string(),5.7, unmovable()}; }; 
    
    int main(){
       //in place construct x,y,z with a string, 5.7 and unmovable.
       auto [x,y,z] = f();
    }

    La bella cosa è che è garantito per non causare qualsiasi la copia o lo spostamento. Si può fare l’esempio many struct variadic troppo. Maggiori dettagli:

    Tornando variadic aggregati (struct) e la sintassi del C++17 variadic modello di costruzione detrazione guida’

  9. 5

    Uso di una struttura o di una classe per il valore di ritorno. Utilizzando std::pair può funzionare per ora, ma

    1. è inflessibile se in seguito si decide che si desidera ulteriori informazioni restituite;
    2. non è molto chiara la funzione della dichiarazione nell’intestazione ciò che viene restituito e in quale ordine.

    Restituzione di una struttura auto-documentante stati i nomi di variabile sarà probabilmente meno soggetta a bug per chiunque utilizzi la funzione. Mettendo la mia collega cappello per un momento, il divide_result struttura è facile per me, un potenziale utente della vostra funzione, per capire immediatamente dopo 2 secondi. A spippolare con parametri di output o misterioso coppie e le tuple vorrebbe più tempo per leggere e può essere utilizzato in modo non corretto. E probabilmente anche dopo aver usato la funzione un paio di volte ho ancora vinto non ricordo l’ordine corretto di argomenti.

  10. 4

    Se la funzione restituisce un valore di riferimento, il compilatore non è in grado di memorizzare in un registro quando la chiamata di altre funzioni perché, in teoria, la prima funzione può salvare l’indirizzo della variabile passato in una globalmente accessibile variabile, e qualsiasi subsecuently funzioni chiamate possono cambiare, in modo che il compilatore abbia (1) salvare il valore dei registri torna alla memoria prima di chiamare altre funzioni e (2) ri-leggere, quando necessario, dalla memoria, di nuovo, dopo una qualsiasi di tali chiamate.

    Se si torna da riferimento, l’ottimizzazione del vostro programma di soffrire

  11. 4

    Qui, sto scrivendo un programma che è tornato a valori multipli(più di due valori) in c++. Questo programma è eseguibile in c++14 (G++4.9.2). è un programma per calcolatore.

    #  include <tuple>
    # include <iostream>
    
    using namespace std; 
    
    tuple < int,int,int,int,int >   cal(int n1, int n2)
    {
        return  make_tuple(n1/n2,n1%n2,n1+n2,n1-n2,n1*n2);
    }
    
    int main()
    {
        int qut,rer,add,sub,mul,a,b;
        cin>>a>>b;
        tie(qut,rer,add,sub,mul)=cal(a,b);
        cout << "quotient= "<<qut<<endl;
        cout << "remainder= "<<rer<<endl;
        cout << "addition= "<<add<<endl;
        cout << "subtraction= "<<sub<<endl;
        cout << "multiplication= "<<mul<<endl;
        return 0;
    }

    Così, si può chiaramente capire che in questo modo si può restituire più valori da una funzione. using std::pair solo 2 valori possono essere restituiti durante std::tupla può restituire più di due valori.

    • Con il C++14 è inoltre possibile utilizzare auto tipo di ritorno sul cal per renderlo ancora più pulito. (IMO).
  12. 4

    Ci sono un sacco di modi per tornare più parametri. Ho intenzione di essere exhastive.

    Utilizzare i parametri di riferimento:

    void foo( int& result, int& other_result );

    utilizzare parametri di puntatore:

    void foo( int* result, int* other_result );

    che ha il vantaggio che è necessario fare un & al call-sito, possibilmente avvisando la gente è un parametro out.

    Scrivere un modello e utilizzarlo:

    template<class T>
    struct out {
      std::function<void(T)> target;
      out(T* t):target([t](T&& in){ *t = std::move(in); }) {}
      out(std::aligned_storage_t<sizeof(T), alignof(T)>* t):
        target([t](T&& in){ ::new( (void*)t ) T(std::move(in)); } ) {}
      template<class...Args>
      void emplace(Args&&...args) {
        target( T(std::forward<Args>(args)...) );
      }
      template<class X>
      void operator=(X&&x){ emplace(std::forward<X>(x)); }
      template<class...Args>
      void operator()(Args...&&args){ emplace(std::forward<Args>(args)...); }
    };

    ce la possiamo fare:

    void foo( out<int> result, out<int> other_result )

    e tutto va bene. foo non è più in grado di leggere qualsiasi valore passato come un bonus.

    Altri modi di definire un punto è possibile inserire i dati possono essere utilizzati per costruire out. Una funzione di callback per emplace le cose da qualche parte, per esempio.

    Siamo in grado di restituire una struttura:

    struct foo_r { int result; int other_result; };
    foo_r foo();

    quale funziona bene in ogni versione di C++, e nel questo consente inoltre di:

    auto&&[result, other_result]=foo();

    a costo zero. I parametri possono nemmeno essere spostato grazie alla garanzia di elisione.

    Abbiamo potuto restituire un std::tuple:

    std::tuple<int, int> foo();

    che ha lo svantaggio che i parametri non sono denominati. Questo permette la :

    auto&&[result, other_result]=foo();

    così. Prima quello che invece si può fare:

    int result, other_result;
    std::tie(result, other_result) = foo();

    che è solo un po ‘ più scomodo. Garantito elisione non funziona qui, però.

    Andando in territorio straniero (e questo dopo out<>!), siamo in grado di utilizzare continuazione passando stile:

    void foo( std::function<void(int result, int other_result)> );

    e ora che i chiamanti:

    foo( [&](int result, int other_result) {
      /* code */
    } );

    un vantaggio di questo stile è che si può restituire un numero arbitrario di valori (con tipo uniforme) senza dover gestire la memoria:

    void get_all_values( std::function<void(int)> value )

    il value richiamata potrebbe essere chiamato a 500 volte quando si get_all_values( [&](int value){} ).

    Per pura follia, si potrebbe anche utilizzare un proseguimento in continuazione.

    void foo( std::function<void(int, std::function<void(int)>)> result );

    il cui utilizzo sembra:

    foo( [&](int result, auto&& other){ other([&](int other){
      /* code */
    }) });

    che avrebbe permesso a molte relazioni tra result e other.

    Di nuovo con uniforn valori, siamo in grado di fare questo:

    void foo( std::function< void(span<int>) > results )

    qui, chiamiamo la richiamata con un arco di risultati. Possiamo anche farlo ripetutamente.

    Usando questo, si può avere una funzione in modo efficiente passa megabyte di dati, senza fare alcuna attribuzione dallo stack.

    void foo( std::function< void(span<int>) > results ) {
      int local_buffer[1024];
      std::size_t used = 0;
      auto send_data=[&]{
        if (!used) return;
        results({ local_buffer, used });
        used = 0;
      };
      auto add_datum=[&](int x){
        local_buffer[used] = x;
        ++used;
        if (used == 1024) send_data();
      };
      auto add_data=[&](gsl::span<int const> xs) {
        for (auto x:xs) add_datum(x);
      };
      for (int i = 0; i < 7+(1<<20); ++i) {
        add_datum(i);
      }
      send_data(); //any leftover
    }

    Ora, std::function è un po ‘ pesante per questo, come avremmo fatto questo a zero costi no-allocazione ambienti. Quindi, vorremmo che la function_view che non alloca.

    Un’altra soluzione è:

    std::function<void(std::function<void(int result, int other_result)>)> foo(int input);

    dove invece di prendere il callback e la invoca, foo restituisce invece una funzione che prende il callback.

    pippo(7)([&](int risultato, int other_result){ /* codice */});
    questo rompe i parametri di uscita dai parametri di ingresso aver separato le staffe.

    Con variant e coroutines, si potrebbe fare foo un generatore di una variante per il ritorno tipi (o solo il tipo di ritorno). La sintassi non è ancora stato fissato, quindi non posso dare esempi.

    Nel mondo dei segnali e slot, una funzione che espone una serie di segnali:

    template<class...Args>
    struct broadcaster;
    
    broadcaster<int, int> foo();

    consente di creare un foo che funziona in modo asincrono e trasmette il risultato al termine.

    Giù per questa linea abbiamo una grande varietà di pipeline tecniche, in cui una funzione non fare qualcosa, ma organizza i dati per essere collegati in qualche modo, e il ciò che è relativamente indipendente.

    foo( int_source )( int_dest1, int_dest2 );

    quindi questo codice non fare nulla fino a int_source ha interi di fornire. Quando lo fa, int_dest1 e int_dest2 iniziare a ricevere i risultati.

    • Questo è un contributo prezioso. Grazie!
    • Questa risposta contiene più informazioni di quante altre risposte! in particolare, informazioni su auto&&[result, other_result]=foo(); per le funzioni di restituzione di entrambi i tuple e strutture. Grazie!
    • Apprezzo la risposta esauriente, soprattutto dal momento che io sono ancora bloccato con C++11 e di conseguenza non è possibile utilizzare alcune delle più moderne soluzioni che altri propongono.
  13. 3

    Tendo a utilizzare vals in funzioni di questo tipo, perché mi attengo al paradigma di una funzione che ritorna il successo/codici di errore e mi piace mantenere le cose uniforme.

  14. 2

    Alternative sono matrici, generatori, e inversion of control, ma nessuno è appropriato qui.

    Alcuni (ad esempio Microsoft storico Win32) tendono ad utilizzare i parametri di riferimento per la semplicità, perché è chiaro che alloca e come apparirà sullo stack, riduce la proliferazione di strutture, e permette di separare il valore di ritorno per il successo.

    “Puro” programmatori preferiscono la struttura, supponendo che è il valore della funzione (come è il caso qui), piuttosto che qualcosa che è toccato accidentalmente dalla funzione. Se si ha una procedura più complicata, o qualcosa con lo stato, si sarebbe probabilmente utilizzare i riferimenti (supponendo che si dispone di un motivo per non usare una classe).

  15. 2

    Direi che non c’è nessun metodo preferito, tutto dipende da che cosa hai intenzione di fare con la risposta. Se i risultati stanno per essere utilizzati insieme in ulteriore elaborazione di strutture di senso, se non avessi tendono a passare poi come singoli riferimenti a meno che la funzione è stata usata in un composito di istruzione:

    x = divide( x, y, z ) + divide( a, b, c );

    Mi capita spesso di scegliere di passare”, al di fuori delle strutture con riferimento a un elenco di parametri invece di avere il pass da copiare sovraccarico di restituzione di una nuova struttura (ma questo è sudare le piccole cose).

    void divide(int dividend, int divisor, Answer &ans)

    Sono i parametri di confusione? Un inviato come parametro di riferimento suggerisce che il valore sta per cambiare (in contrapposizione a un const reference). Denominazione sensata rimuove anche confusione.

    • Penso che sia un po ‘ di confusione. Qualcuno di lettura di codice che chiama si vede “divide(a,b,c);”. Non c’è alcuna indicazione che c è un outval fino a guardare in alto la firma. Ma è una paura generale di riferimento non const params, piuttosto che particolare a questa domanda.
  16. 2

    Perché insisti a una funzione con più valori di ritorno? Con l’OOP è possibile utilizzare una classe che offre una funzione regolare con un unico valore di ritorno, e qualsiasi numero di altri “valori di ritorno”, come di seguito. Il vantaggio è che il chiamante ha una scelta di guardare i dati aggiuntivi membri, ma non è richiesto per fare questo. Questo è il metodo preferito per la complicata base di dati o di rete chiamate, dove un sacco di ulteriori restituire informazioni possono essere necessarie in caso di errori.

    Per rispondere alla tua domanda originale, in questo esempio, il metodo per restituire il quoziente, che è ciò che la maggior parte dei chiamanti possono avere bisogno, e inoltre, dopo la chiamata al metodo, è possibile ottenere il resto come membro di dati.

    class div{
       public:
          int remainder;
    
          int quotient(int dividend, int divisor){
             remainder = ...;
             return ...;
          }
    };
    • Peccato che il downvoter non si cura di dirci perché la mia soluzione non è utile. Fortunatamente, mi sono divertito con questo metodo un sacco di volte io stesso.
    • Penso che ci sono casi in cui questo è inefficiente. E. g. si dispone di un unico ciclo for che genera diversi valori di ritorno. Se dividi quei valori in funzioni separate avresti bisogno di correre attraverso il ciclo una volta per ogni valore.
    • Si potrebbe eseguire il ciclo una volta e memorizzare i diversi valori di ritorno in classe separata membri di dati. Questo sottolinea la flessibilità del concetto di OOP.
  17. 2

    anziché restituire più valori,appena ritorno di uno di loro e fare un riferimento di altri in funzione necessaria, per esempio:

    int divide(int a,int b,int quo,int &rem)
    • Ho fatto a non parlare di questo nella domanda stessa? Inoltre, vedere le mie obiezioni in la mia risposta.
  18. 1

    Boost tupla sarebbe la mia scelta preferita per un sistema generalizzato di restituire più di un valore da una funzione.

    Possibile esempio:

    include "boost/tuple/tuple.hpp"
    
    tuple <int,int> divide( int dividend,int divisor ) 
    
    {
      return make_tuple(dividend / divisor,dividend % divisor )
    }
  19. 1

    Siamo in grado di dichiarare la funzione tale che, restituisce un tipo di struttura variabile definita dall’utente o un puntatore ad esso . E la struttura di una struttura, sappiamo che una struttura in C può contenere più valori di asimmetrico tipi (cioè una variabile int, quattro variabili char, due variabili float e così via…)

  20. 1

    Vorrei semplicemente fare da riferimento se è solo un paio di valori di ritorno, ma per i tipi più complessi si può anche fare così :

    static struct SomeReturnType {int a,b,c; string str;} SomeFunction()
    {
      return {1,2,3,string("hello world")}; //make sure you return values in the right order!
    }

    uso “statico” per limitare l’ambito di applicazione del tipo di ritorno di questa unità di compilazione, se è solo destinato ad essere temporaneo tipo di ritorno.

     SomeReturnType st = SomeFunction();
     cout << "a "   << st.a << endl;
     cout << "b "   << st.b << endl;
     cout << "c "   << st.c << endl;
     cout << "str " << st.str << endl;

    Questo non è sicuramente la più bella strada da fare, ma è lavoro.

Lascia un commento