Sebbene ciò non sia esattamente non valido, non è una buona idea.
MyClass& doSomething() {
return *(new MyClass());
}
Al rientro, nessuno ha il puntatore originale, in modo che nessuno potrà mai delete
esso. * Quindi è una perdita di memoria.
si dovrebbe praticamente mai scrivere un new
se non si ha un corrispondente delete
-o, meglio, un costruttore puntatore intelligente.
Nel frattempo, questa riga nel codice originale: ... sta andando
MyClass a = doSomething();
di fare una copia del valore in ogni caso. Supponendo che non fosse un altro bug da correggere, perché preoccuparsi di allocare un heap all'oggetto e restituire un riferimento a copia e perdita? Basta restituire l'oggetto per valore:
MyClass doSomething() {
return MyClass();
}
Ora non c'è bisogno di preoccuparsi di cancellare nulla, perché non hai mai creato nulla sul mucchio.
Le best practice possono in genere essere riassunte nelle quattro lettere RAII: Acquisizione risorsa è inizializzazione. (E il corollario, quella distruzione è il rilascio.) Se hai qualcosa che è impossibile, o costoso, da passare in giro per valore, allora passa attorno ad un handle per valore. Ad esempio:
unique_ptr<MyClass> doSomething() {
return unique_ptr<MyClass>(new myClass());
}
unique_ptr<MyClass> a = doSomething();
Ora è solo un puntatore che viene copiato. L'oggetto stesso viene creato all'interno di doSomething
e cancellato ogni volta che a
esce dallo scope (o, se lo si passa ad un'altra variabile, ogni volta che che esce dal campo di applicazione, ecc.).
D'altra parte, se MyClass
è solo una manciata di valori facilmente copiabili **, basta copiarlo.
* Non è impossibile per cancellare mai esso; puoi sempre prendere un puntatore al riferimento e delete
. È molto improbabile che lo farai mai, e sembrerà imbarazzante. Se vuoi passare i puntatori, passa i puntatori. Se non si desidera passare i puntatori in giro, avvolgere la proprietà in una classe e passare la classe in base al valore.
** Con "facilmente copiabili" intendo che è facile copiarli in modo sicuro e che lo si fa effettivamente. Ad esempio, un puntatore raw o un handle di file sono solo pochi byte, e il costruttore di copie predefinito li copierà volentieri per te ... ma poi finirai con più riferimenti allo stesso oggetto o file heap, ed è impossibile tenere traccia di chi ha il compito di cancellarlo o chiuderlo.
No const necessario, la prima opzione è buona. Inoltre, puoi anche restituire un puntatore se lo desideri. Sta a te. –
Ma il riferimento non è stato assegnato dal chiamante. È stato istanziato durante la chiamata ... ho pensato che se non avessi usato di nuovo, sarebbe andato fuori portata perché sarebbe stato in pila piuttosto che in un heap. –
@BrianCain Ha assolutamente bisogno di 'new', perché altrimenti l'oggetto verrà distrutto non appena termina' doSomething() '. –