2011-10-17 14 views
5

Supponiamo di avere una funzione che restituisce un risultato importante e diversi risultati non importanti. Ho dichiarato in modo che i risultati non importanti vengono restituiti con riferimento:Ignorare un risultato di ritorno per riferimento di una funzione

int CalculateStuff(int param1, int param2, int& result1, int& result2); 

Vorrei chiamare questa funzione per calcolare alcune cose, ma al sito di chiamata voglio ignorare i risultati poco importanti. Ho potuto fare come segue:

... 
int dummy1, dummy2; 
int result = CalculateStuff(100, 42, dummy1, dummy2); 
... // do something with the result 

desidero considerare un altro modo per fare la stessa senza dichiarare variabili dummy:

int result = CalculateStuff(100, 42, *new int, *new int); 

Questo ha una perdita di memoria (inaccettabile), ma ha un vantaggio di mostrare il mio intento (ignorando i risultati) più chiaramente dei nomi "fittizi".

Allora, che cosa accadrebbe se ho scritto come segue:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get()); 

E 'legale? Gli interi temporanei esistono ancora quando viene eseguito il codice della funzione? Dovrei usare unique_ptr invece di auto_ptr?

(Si prega di non suggeriscono refactoring il mio codice, io probabilmente - ma prima voglio capire come funziona questa roba)

+1

Aggiunto come commento in quanto in realtà non risponde alla tua domanda - ma di solito dichiaro un messaggio temporaneo chiamato _ e passa che se questo viene fuori. "CalculateStuff (100, 42, _, _); sembra ragionevolmente chiaro – jcoder

risposta

4

è legale; Gli oggetti auto_ptr rimarranno in vita fino alla fine dell'espressione (ad esempio chiamata di funzione). Ma è brutto da morire.

Basta sovraccaricare la vostra funzione:

int CalculateStuff(int param1, int param2, int& result1, int& result2); 
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2); 
} 
+1

Che ancora implora la * stessa * domanda, come implementerai il secondo sovraccarico? Userai le variabili dummy, o' * new int' o 'auto_ptr', o cosa, in modo da poter chiamare il primo sovraccarico dal secondo? – Nawaz

+0

@Nawaz, ad esempio, creando due variabili temporanee o chiamando qualche terza implementazione (ad esempio quella con i puntatori suggeriti). – hamstergene

+0

Ma Questa è esattamente la domanda: – Nawaz

3

Un approccio consigliato se si ha il controllo sulla funzione sarebbe: restituire un std::tuple (o boost::tuple) con tutti i risultati o scrivere un sovraccarico che non ha bisogno l'extra variabili.

3

Ecco il mio consiglio: se devi chiedere a SO di capire la correttezza del codice e della sua semantica, allora il codice non riesce a esprimere chiaramente il tuo intento.

Penso che la prima versione (con dummy1 e dummy2) sia la più trasparente, ed è ovviamente corretta.

Se vi trovate a volte chiamando la funzione e non volendo i risultati opzionali, si potrebbe fornire un sovraccarico:

int CalculateStuff(int param1, int param2, int& result1, int& result2) {} 

int CalculateStuff(int param1, int param2) { 
    int unwanted1, unwanted2; 
    return CalculateStuff(param1, param2, unwanted1, unwanted2); 
} 
4

Secondo Bjarne Stroustrup, se alcuni parametri sono opzionali, si tratta di un caso ideale per fare li tipo di puntatore, in modo che è possibile passare NULL quando non è necessario passare gli argomenti per loro:

int CalculateStuff(int param1, int param2, int * result1, int * result2); 

E l'uso:

int result = CalculateStuff(100, 42, NULL, NULL); 

Tutte le altre alternative non sarebbero buone come questa, o almeno non meglio di.

Ovviamente, l'implementazione di CalculateStuff deve controllare i parametri se sono NULL oppure no.

3

È possibile creare una classe che fornisca una conversione implicita (o esplicita) a int&.

struct ignored 
{ 
    int n; 
    operator int&() { return n; } 
}; 

n = CalculateStuff(a, b, ignored(), ignored()); 

È possibile rendere ulteriormente questo modello e aggiungere sovraccarichi const.

+0

non sarà il tipo di ignorato essere const e ti darà problemi? –

+0

@WinstonEwert: Perché? Un temporaneo non può legarsi direttamente a un riferimento non-const. Tuttavia, si possono chiamare metodi non const di un oggetto temporaneo. Questo è ciò che sta sfruttando. – UncleBens

2

È legale, ma non è garantito che non vi siano perdite di memoria, vedere la domanda 3 here ad esempio.

Il modo corretto e idiomatica di attuare uscita opzionale è di passare un puntatore, passando NULL quando non si desidera che i risultati, e la sperimentazione per NULL nella funzione prima di scrivere attraverso il puntatore.

Problemi correlati