Ci sono alcuni motivi per cui potrebbe essere utile.
Tipi non copiabili
Non tutto può essere passato per valore! std::unique_ptr
, ad esempio, può essere spostato, non copiato, perché non ha senso copiare qualcosa che ha proprietà uniche su una risorsa. Il suo costruttore di copie è stato "cancellato", il che significa che passarlo per valore in una funzione semplicemente fallirà.
Tipi di grandi dimensioni
Forse la tua funzione ha solo bisogno di ispezionare il valore corrente dell'oggetto, senza effettivamente cambiarlo. Se l'oggetto è grande, la copia è inutile e inutile. Non solo stai prendendo più cicli di memoria e CPU di quelli di cui hai bisogno, ma se hai una ricorsione profonda, sì puoi davvero contribuire alla probabilità di un sovraccarico di stack perché i tuoi stack frame sono molto più grandi di quanto dovrebbero essere. p>
In genere, in questi scenari, passeremo da const
di riferimento per evitare le mutazioni accidentali.
Mutation
Forse l'oggetto viene passato come parametro "out", in modo che le modifiche apportate all'interno della funzione siano visibili nel sito di chiamata. Ecco un esempio:
bool foo(std::string& a)
{
const char* result = someSysCall("...");
if (result) {
a = result;
return true;
}
else {
return false;
}
}
int main()
{
std::string str;
if (foo(str)) {
// do things with str
}
else {
// show an error?
}
}
Mentre spesso usiamo le eccezioni invece di questo schema, i parametri out sono ancora diffusi in molte librerie (in particolare l'API di Windows). Spesso vengono implementati utilizzando puntatori, ma il principio è esattamente lo stesso.