Non sorprende che ciò dipenda dallo scopo della funzione e dalla natura del tipo che sta recuperando / estraendo. Ma di solito è facile fare una scelta in base alle proprietà del tipo.
1) Il valore è un elemento primitivo come int
o char
Quindi la scelta è effettivamente tra:
int x = getInt();
e
int x;
setInt(x);
Preferisco strongmente restituire il valore, perché:
- Sembra solo più naturale / normale / intuitivo / leggibile / ecc.
- Ora che la funzione accetta un argomento, è possibile che il suo comportamento dipende dal valore corrente di tale argomento. Semanticamente, il valore corrente di x è completamente irrilevante rispetto a ciò che fa questa funzione, quindi perché dare alla funzione l'accesso ad esso?
- Copiare e assegnare
int
s costa praticamente nulla. Le probabilità sono entrambe le versioni ottimizzate per le stesse istruzioni comunque.
2) Il valore è una struct / class "banale" (ad esempio, nessun dato privato, metodi o gestione della memoria)
Presumo che la tua classe Mouse_Position rientra in questa categoria. Questo caso è fondamentalmente identico al n. 1, perché una classe come questa si comporta più o meno come una primitiva.
Più formalmente, quando dico che questa classe è come un valore primitivo, sto dicendo che questa classe ha "semantica del valore". Ciò significa un sacco di cose, ad esempio se due oggetti di quella classe hanno gli stessi membri dei dati, sono completamente intercambiabili a tutti gli effetti. Questa è una proprietà molto bella da avere quando si tratta di ragionare sul proprio codice.
3) Il valore ha metodi / dati privati / gestione della memoria, ma implementa RAII e ancora tecnicamente ha semantica del valore
È qui che vanno le classi del contenitore STL. Un vettore std :: contiene sicuramente dati privati, tra cui un puntatore alla memoria che deve gestire manualmente, ma i suoi costruttori, i distruttori e le operazioni di copia sono implementati in modo tale da comportarsi ancora come un valore primitivo in molti modi. In particolare, due vettori che si confrontano uguali sono ancora intercambiabili; non importa in che regione della memoria si trovano i loro valori.
In questo caso, se si restituisce per valore o si prende un parametro di riferimento si riduce in genere all'efficienza. In C ++ normalmente non si desidera copiare classi come questa se non è necessario, perché ciò implica la copia di tutti i dati privati o la memoria che viene gestita (il che potrebbe comportare l'allocazione di più memoria). Tuttavia, spostare la semantica nel moderno C ++ fa in modo che la restituzione di uno std :: vector non esegua necessariamente più una copia, quindi semplicemente restituirla per valore sta diventando più accettabile (non cercherò di spiegare le condizioni esatte in cui le copie fanno / non succede prima / dopo C ++ 11, è troppo complicato).
4) Il valore non ha traccia di semantica del valore e la conservazione della sua identità è importante
Di solito sono classi che rappresentano dipendenze esterne come file, database, connessioni di rete, dispositivi periferici, contesti di rendering e così via. Spesso non ha senso copiare questi oggetti (non è possibile dare al computer più tastiere copiando una classe Keyboard
), quindi le funzioni che operano su di essi devono fondamentalmente operare su puntatori / riferimenti ad essi come una semplice questione di correttezza. Ovviamente qui la decisione è presa per te.
Risposta breve: non utilizzare puntatori / riferimenti quando sono completamente inutili. La semplice copia / restituzione dei valori spesso porta a un codice più intuitivo e con un comportamento migliore.