2011-08-25 6 views
8
string foo() { return "hello"; } 
int main() 
{ 
    //below should be illegal for binding a non-const (lvalue) reference to a rvalue 
    string& tem = foo(); 

    //below should be the correct one as only const reference can be bind to rvalue(most important const) 
    const string& constTem = foo(); 
} 
  1. GCC è quello buono che invia un errore compilazione: inizializzazione valido di riferimento non const di tipo std::string& da un temporaneo di tipo std::string
  2. VS2008 non è male come almeno dà un compilazione avvertimento: C4239 avviso: estensione non standard utilizzata: 'inizializzazione': conversione da std::string a std::string & a riferimento non-const può essere associato solo ad un Ivalue
  3. Ecco la problematica: VS2010 (SP1) compatta bene SENZA qualsiasi errore , PERCHÉ ?? !! Io so il riferimento di valore in VS2010 può essere utilizzato per eseguire il bind con il valore di rvalue ma NON sto usando &&, invece nel codice demo, stavo usando solo il riferimento di lvalue non-const!

Qualcuno può aiutarmi a spiegare il comportamento di VS2010 qui? E 'un errore !? GrazieUn bug VS2010? Permettere il riferimento non const-vincolante al rvalore SENZA UN EVENTO?

+1

quali sono le impostazioni di avviso? Forse è la tua configurazione che è cambiata, e non la loro implementazione? –

+0

Utilizzo VS2008 da un po 'di tempo ma recentemente ho installato VS2010, quindi VS10 dovrebbe usare le impostazioni predefinite ... – Gob00st

+2

quindi temo che la soglia di avviso non sia abbastanza alta. Usa '\ W4' per attivare gli avvertimenti nell'intervallo' 4xxx'. –

risposta

11

Questo è un problema noto/funzionalità dei compilatori VS. Lo hanno sempre permesso e non sembra esserci alcuna spinta a rimuovere l'estensione .

+0

Qualche idea sul perché MS abbia consentito questo uso illegale di C++ in primo luogo? Questa particolare regola di riferimento dovrebbe essere piuttosto vecchia (98 o 03 standard)? – Gob00st

+0

@ Gob00st: questa è un'estensione che elude la limitazione C++ arbitraria. Personalmente penso che l'associazione debba essere consentita o respinta e che l'attuale * mezzo-permesso * sia davvero uno stato imbarazzante. Disabilitato del tutto eliminerebbe un'intera classe di bug, anche se sarebbe doloroso, Permesso interamente raddrizzerebbe le specifiche. –

+2

@ Gob00st - MS ha un vecchio codice che è stato scritto prima che le regole venissero corrette (e così potrebbero avere i loro clienti).Ritengono che sia più importante supportare il vecchio codice rispetto ai nuovi standard. È anche possibile disattivare le estensioni (e quindi non essere in grado di compilare alcune intestazioni di Windows). –

9

Il compilatore genera un errore con Disattiva estensioni lingua attivato e un avviso su/W4. Tuttavia, la rimozione di questo codice interromperà il codice precedentemente compilato e Microsoft è molto riluttante a farlo. Questo è anche il motivo per cui non risolveranno il loro supporto SFINAE.

+0

Forse vale la pena ricordare che l'avviso è stato spostato da/W3 a/W4 in VS2010. – rustyx

-1

C'è una variante molto più cattiva di questo problema:

Quindi: a che cosa fa b.f punto durante la chiamata a b.F()? L'esempio precedente, compilato con le impostazioni di debug VS2013 predefinite, funziona senza arresti anomali e stampa 3, ma sospetto che un esempio molto più complesso porterà alla corruzione dello stack. Se non lo fa e il compilatore sta facendo qualcosa di "intelligente" per farlo funzionare, allora immagino che cosa stia facendo davvero:

class Foo { 
    int _val; 
public: 
    Foo(int v) : _val(v) {} 
    void F() { std::cout << _val << std::endl; } 
}; 

class Bar { 
    Foo f; 
public: 
    Bar(Foo&& f) : f(f) {} 
    void F() { f.F(); } 
}; 

int main() { 
    Bar b(Foo(3)); 
    b.F(); 
} 
+0

Si noti che questo stesso problema esiste se 'f' era invece un riferimento const e che sarebbe consentito dallo standard. –