2009-03-20 29 views
10

Stavo leggendo C++ Faq Second Edition, numero faq 32.08.Parametro passato con riferimento const restituito da riferimento const

FAQ dice che il parametro passato da riferimento const e restituito da riferimento const può causare riferimento ciondolante.

Ma va bene se il parametro viene passato per riferimento e restituito per riferimento.

Ho capito che non è sicuro in caso di riferimento const ma come è sicuro nel caso in cui il parametro non è riferimento const.

ultima linea di FAQ dice "Si noti che se una funzione accetta un parametro di riferimento non-const (ad esempio, f (string & s)), restituendo una copia di questo parametro di riferimento è sicuro perché un temporaneo non può essere passato da riferimento non const. "

Hai bisogno di qualche intuizione su questo !!

+0

Non sono sicuro di cosa intendi su Faq Seconda edizione. puoi pubblicare l'Url su di esso? –

+0

http://www.amazon.com/FAQs-2nd-Marshall-P-Cline/dp/0201309831/ref=sr_1_1?ie=UTF8&s=books&qid=1237575374&sr=8-1 – anand

+0

ok vedo. molte faq là fuori e non era nel famoso online faq C++ e poi mi chiedevo cosa fosse :) –

risposta

31

se avete come

const Foo & bar(const Foo &f) { return f; } 

e chiamarlo come

const Foo &ret = bar(Foo()); 

Questo compila, ma il problema è che la società 'ret' è un riferimento ciondolante, perché l'oggetto temporaneo creato dalla chiamata a Foo() viene liberato dopo la restituzione della barra. La sequenza di esecuzione dettagliata ecco:

  1. temporanea Foo è allocato
  2. bar è chiamato con un riferimento all'oggetto temporaneo
  3. bar restituisce il riferimento
  4. ora che bar è tornata Foo temporanea viene rilasciato
  5. il riferimento è ora penzolava come l'oggetto è stato distrutto

Tuttavia, se si ha dichiarato come Foo

Foo & bar(Foo &f) { return f; } 

allora la vostra barra di chiamata (Foo()) non sarebbe accettato da compilatore. Quando si passa un oggetto temporaneo a una funzione, è possibile prenderlo solo per riferimento const o come copia; questo fa parte della definizione del linguaggio.

+0

Modifica: 'ref' dovrebbe essere 'ret' Quindi significa che const Foo & può essere associato a Foo() temporaneo ma Foo & non può associarsi a Foo() temporaneo. Qualche idea sul perché il compilatore non lo consenta? – anand

+2

antti, buona risposta :) –

+0

non è consentito perché i riferimenti non convenzionali devono fare riferimento a oggetti con nome. questo è principalmente per sicurezza, ma ha anche ragioni più teoriche. se un valore temporaneo non di classe come int potrebbe legarsi a un riferimento non conforme, int avrebbe bisogno di un indirizzo (essere un oggetto). ma non è un oggetto - solo un valore –

3

I temporanei possono essere passati per riferimento const - quando la funzione restituisce i provvisori vengono smontati, quindi il chiamante viene lasciato con un riferimento ciondolante.

Ad esempio:

#include <iostream> 

using namespace std; 

int const& output(int const& x) 
{ 
    cout << x << endl; 

    return x; 
} 

int main() 
{ 
    int a = 1; 

    int const& ref1 = output(a); // OK 

    int const& ref2 = output(a+1); // bad 

    return 0; 
} 
1

penso che questo esempio sarà utile:

const int& f(const int& n) 
{ 
    return n; 
} 

int f1(int& n) 
{ 
    return n; 
} 


int main(int argc, char **argv) 
{ 
    //Passing a reference to an anonymous object created by 
    //the compiler to function f() 
    const int& n = f(10); 

    //Undefined behavior here as the scope of the anonymous object 
    //was only till previous statement 
    int k = n + 10; 

    //Compiler error - Can not pass non-const reference to a anonymous object 
    int n = f1(10); 
} 
1

Here è una pagina di C++ 0x rvalue riferimenti che inizia con un riassunto abbastanza decente di come lvalue e rvalues ​​lavorano in C++, insieme con il modo in cui sono autorizzati a legare con riferimenti.

La maggior parte degli articoli che troverete sui riferimenti di rvalue in C++ 0x vi daranno un'idea di questo.

Problemi correlati