2010-04-02 12 views
10

È questo il modo corretto per restituire un oggetto da una funzione?Restituzione di un oggetto locale da una funzione

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

displayCar(getCar("Honda", 1999)); 

Ho ricevuto un errore, "indirizzo di temporaneo". Dovrei usare in questo modo:

Car &getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

risposta

23

getCar restituisce un Car per valore, che è corretto.

Non è possibile passare tale valore di ritorno, che è un oggetto temporaneo, in displayCar, perché displayCar prende uno Car&. Non è possibile associare un riferimento temporaneo a un riferimento non const. Si dovrebbe cambiare displayCar di prendere un riferimento const:

void displayCar(const Car& car) { } 

In alternativa, è possibile memorizzare il temporaneo in una variabile locale:

Car c = getCar("Honda", 1999); 
displayCar(c); 

Ma, è meglio avere displayCar prendere un riferimento const dal momento che doesn modificare l'oggetto.

Non restituire un riferimento alla variabile locale Car.

+0

puoi anche memorizzare il temporaneo senza invocare il costruttore di copie (che si trova in 'Car c = getCar (...)' usando un riferimento a const: 'const Car & c = getCar (...)', se non si Non è necessario apportare modifiche tramite 'c' dopo. –

4

Non è sicuro restituire il riferimento di una variabile locale da una funzione.

Quindi sì questo è corretto:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 
+0

Hmm, ho bisogno di qualcosa come una funzione di fabbrica che creerà un oggetto e lo restituirà. – pocoa

+1

Molti (la maggior parte?) Compilatori ottimizzano 'return Car (model, year)' in modo che non sia necessaria alcuna copia aggiuntiva, quindi mi libererei della variabile locale esplicita. –

+0

@Steven: molti (più?) Compilatori implementano anche l'ottimizzazione del valore di ritorno (NRVO), quindi non c'è generalmente alcuna differenza. –

8

Il tuo problema è:

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

si dovrebbe utilizzare un riferimento const:

void displayCar(const Car & car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

Questa funzione:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

è OK così com'è, ma tutto quello che sta facendo è ciò che fa il costruttore, quindi è ridondante. Il passaggio di un valore di schiena, piuttosto che un punto di riferimento, è la cosa giusta da fare per questo tipo della funzione, tuttavia, il parametro modello dovrebbe essere passato per riferimento const:

Car getCar(const string & model, int year) { 

In generale, per i tipi di classe come stringa o Car, la scelta predefinita per un parametro dovrebbe sempre essere un riferimento const.

0

Ancora meglio:

Car getCar(string model, int year) { 
     return Car(model, year); 
} 
+0

Nella mia risposta si trattava esattamente di cosa intendevo per" operazioni di copia "Sebbene al momento questa sia la soluzione standard, è un'operazione molto più costosa del semplice invio di un indirizzo. – themoondothshine

+1

@themoondothshine : Molti compilatori (tutti quelli che conosco) eseguiranno RVO qui, quindi è un'operazione davvero economica. –

2

Sì, è sicuramente non è sicuro per restituire un riferimento o un puntatore a un oggetto temporaneo. Quando scade (cioè, quando la funzione getCar termina), ti verrà lasciato ciò che è noto come "puntatore penzolante".

Tuttavia, se si desidera ridurre le operazioni di copia su un oggetto, è necessario controllare "Move semantics" di C++ 0x. È un concetto relativamente nuovo, ma sono sicuro che diventerà presto il flusso principale. GCC 4.4 verso l'alto supporta C++ 0x (utilizzare l'opzione del compilatore -std=c++0x per abilitare).

Problemi correlati