Risponderò alla tua domanda ... il contrario.
perché hanno permesso Foo const& foo = fooByValue();
per cominciare?
rende la vita (un po ') più facile, ma introduce il potenziale comportamento non definito in tutto il luogo.
Foo const& fooByReference()
{
return fooByValue(); // error: returning a reference to a temporary
}
Questo è ovviamente sbagliato, e in effetti il compilatore lo riferirà doverosamente. Come da commento di Tomalak: non è obbligatorio dallo standard, ma i buoni compilatori dovrebbero segnalarlo. Clang, gcc e MSVC fanno. Penso che anche Comeau e Icc lo farebbero.
Foo const& fooByIndirectReference()
{
Foo const& foo = fooByValue(); // OK, you're allowed to bind a temporary
return foo; // Generally accepted
}
Questo è sbagliato, ma è più sottile. Il problema è che la durata del temporaneo è legata alla durata di foo
, che esce dall'ambito alla fine della funzione. A copia di foo
viene passato al chiamante e questa copia punta nell'etere.
Ho sollevato il bug su Clang, e Argyris è riuscito a diagnosticare questo caso (complimenti davvero: p).
Foo const& fooForwarder(Foo const&); // out of line implementation which forwards
// the argument
Foo const& fooByVeryIndirectReference()
{
return fooForwarder(fooByValue());
}
La temporanea creata da fooByValue
è legata alla durata di vita l'argomento della fooForwarder
, che doverosamente fornire una copia (di riferimento), copia che viene restituito al chiamante, anche se ora punta nell'etere .
Il problema qui è che l'implementazione di fooForwarder
è perfettamente soddisfacente rispetto allo standard e tuttavia crea un comportamento non definito nel relativo chiamante.
Il fatto scoraggiante, tuttavia, è che la diagnosi di questo richiede la conoscenza dell'implementazione di fooForwarder
, che è fuori dalla portata del compilatore.
L'unica soluzione che riesco a capire (a parte il WPA) è una soluzione runtime: ogni volta che un temporaneo è limitato a un riferimento, è necessario assicurarsi che il riferimento restituito non condivida lo stesso indirizzo ... e quindi che cosa ? assert
? sollevare un'eccezione? E poiché è solo una soluzione runtime, non è chiaramente soddisfacente.
L'idea di associare un riferimento temporaneo a un riferimento è fragile.
Non è la stessa domanda discussa da Herb Sutter qui http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/? – DumbCoder
@DumbCoder: no, Herb Sutter progetta l'utilizzo dello standard C++ mentre Fred discute la logica dietro lo standard. –