Domanda

Si prega di prendere in considerazione le tre funzioni.

std::string get_a_string()
{
    return "hello";
}

std::string get_a_string1()
{
    return std::string("hello");
}

std::string get_a_string2()
{
    std::string str("hello");
    return str;
}
  1. Verrà RVO essere applicata in tutti e tre i casi?
  2. E 'OK per restituire un temporanea come nel codice qui sopra? Credo che sia OK dal momento che sto tornando per valore invece di tornare ogni riferimento ad esso.

Qualche idea?

È stato utile?

Soluzione

In due primi casi di ottimizzazione RVO avrà luogo. RVO è vecchio funzione e la maggior parte dei compilatori lo supporta. L'ultimo caso è così chiamato NRVO (nome RVO). Questo è relativamente nuova caratteristica del C ++. Standard permette, ma non richiede attuazione NRVO (così come RVO), ma alcuni compilatori lo supporta.

Si potrebbe leggere di più su RVO al punto 20 di Scott Meyers libro più efficace C ++. 35 nuovi modi per migliorare i vostri programmi e disegni .

Qui è un buon articolo su NRVO in Visual C ++ 2005.

Altri suggerimenti

In primo luogo, è completamente a posto per restituire un provvisorio in base al valore che è quello che si fa. Esso viene copiato e anche se l'originale andrà fuori portata la copia non lo farà e può essere utilizzato in modo sicuro dal chiamante.

In secondo luogo, tutti e tre i casi sono di fatto identiche (in quanto non si accede alla temporanea nel terzo caso comunque) e un compilatore potrebbe anche emettere lo stesso codice per tutti loro. Quindi può utilizzare RVO in tutti e tre i casi. Ciò è del tutto compilatore-dipendente.

Tutti i casi sono corrette. Tutti potranno costruire una temporanea e applicare il costruttore di copia del tipo di ritorno. Necessariamente, se non v'è alcun costruttore di copia, il codice avrà esito negativo.

RVO accadrà su tutti e tre i casi sotto la maggior parte dei compilatori. L'unica differenza è l'ultimo in cui la norma non forzarlo. Questo perché si ha una variabile chiamata. Ma la maggior parte dei compilatori sono abbastanza intelligenti da applicare RVO ad esso ancora ... il più tardi la variabile chiamata è dichiarata e le meno trasformazioni che viene applicato, le quote migliori per RVO da applicare a una variabile denominata.

Per inciso, che restituisce un riferimento è naturalmente possibile, come si potrebbe avere visto in altro codice. Quello che non si deve fare è restituire un riferimento t un oggetto locale.

std::string& get_a_string2()
{
    std::string str("hello");
    return str; //error!
}

Genera un errore di compilazione, come sapete. Tuttavia,

std::string& get_a_string2(std::string& str)
{
    // do something to str
    return str; //OK
}

funzionano bene. Su questo caso, non c'è costruzione o la copia di costruzione coinvolte. Semplicemente la funzione restituisce un riferimento al suo argomento.

  1. Dipende dal vostro compilatore - quale piattaforma ti riferisci? Il modo migliore per scoprirlo è quello di compilare un molto piccolo test app e controllare l'ASM compilatore produce.

  2. Sì, va bene, anche se non parlare di quello che si sta in questione; velocità? stile? è possibile una temporanea locale a un riferimento const - la durata della temporanea sarà esteso a tutta la vita del riferimento - provare e vedere di persona! (Herb Sutter exaplins questo qui ) Vedi fine del post, per esempio.

IMO si è quasi sempre meglio confidando il compilatore per ottimizzare il codice per voi. Ci sono pochissimi casi in cui dovreste aver bisogno di preoccuparsi di questo genere di cose (codice di livello molto basso è una di queste zone, dove sei interattiva con registri hardware).

int foo() { return 42; }

int main(int, char**)
{
    const int &iRef = foo();
    // iRef is valid at this point too!
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top