In http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ si menziona "most important const" dove C++ specifica deliberatamente che legare un oggetto temporaneo a un riferimento a const sullo stack allunga la durata del temporaneo alla durata del riferimento stesso. Mi chiedevo perché il C++ consente di allungare la vita dell'oggetto solo quando il riferimento è const e non quando non lo è? Qual è il razionale dietro la funzione e perché deve essere const?Perché la "più importante const" deve essere const?
risposta
Si consideri il seguente:
int& x = 5;
x = 6;
quello che dovrebbe accadere se questo è stato permesso? Al contrario, se l'avete fatto
const int& x = 5;
non ci sarebbe alcun modo legale per modificare x
.
Dovrebbe essere creata una variabile locale nascosta con valore 5. Non c'è motivo tecnico per non permetterlo. –
@NeilKirk Tuttavia, non è qualcosa che ci si aspetta da 'int &', sarebbe solo un peso per i progettisti del compilatore e non sarebbe diverso da 'int x = 5'. –
@tohecz ma questo è il modo in cui il binding con const è implementato con i valori restituiti dalle normali funzioni. Tutte le funzionalità sono "fardelli" per i progettisti del compilatore, non è un motivo per non essere una caratteristica! – dan
Ecco un esempio:
void square(int &x)
{
x = x * x;
}
int main()
{
float f = 3.0f;
square(f);
std::cout << f << '\n';
}
Se provvisori potrebbero legarsi a riferimenti lvalue non const, quanto sopra sarebbe felicemente compilare, ma produrre risultati piuttosto sorprendenti (una potenza di 3
invece di 9
).
Interessante, non ci avevo pensato. –
Perché dovrebbe emettere 3? – 0x499602D2
Questa è la solita spiegazione, penso. Cosa accadrebbe se fosse consentito nell'inizializzazione in stile copia, ma non nell'inizializzazione dei parametri? Esistono già conversioni esplicite o implicite. –
Si noti che i riferimenti const possono essere associati a oggetti che non hanno nemmeno un indirizzo normalmente. Un parametro di funzione const int &
può accettare un argomento formato dall'espressione costante letterale 42
. Non possiamo prendere l'indirizzo di 42
, quindi non possiamo passarlo a una funzione che prende uno const int *
.
I riferimenti const sono appositamente "benedetti" per poter essere associati a valori come questo.
Ovviamente, per i rvalori tradizionali come 2 + 2
, la durata non è un problema. È un problema per i rvalues del tipo di classe.
Se il legame di un riferimento è consentito a qualche oggetto che, a differenza 42
, non hanno una vita diffusa, quella vita ha da estendere, in modo che il riferimento rimane sano per tutta la sua portata.
Non è che il const causi un'estensione di durata, è che un riferimento non const non è consentito. Se fosse permesso, richiederebbe anche un'estensione a vita; non ha senso permettere qualche riferimento che poi va male in alcune parti del suo campo di applicazione. Questo comportamento mina il concetto che un riferimento sia più sicuro di un puntatore.
- 1. Perché la variabile const non deve essere inizializzata in C?
- 2. Perché questa dichiarazione const const const valido
- 3. NON il più importante const .. ma cos'è questo?
- 4. Qual è la differenza tra const const e const?
- 5. const vs new const
- 6. const int = int const?
- 7. Const vettore di non-const oggetti
- 8. oggetto const e costruttore const
- 9. Differenza tra const & const volatili
- 10. const CFoo e bar() const
- 11. Come inizializzare correttamente una variabile const const const?
- 12. La conversione da const char * a const std :: string &
- 13. Un constexpr è più "costante" di const?
- 14. Sovraccarico dell'operatore Const e Non-Const
- 15. Perché una dichiarazione enum dovrebbe essere marcata const?
- 16. Perché il riferimento const può essere riassegnato in istruzione for?
- 17. metodi const e no const in C++?
- 18. funzione template overloading: const * contro const &
- 19. Perché un'interfaccia deve essere dichiarata di nuovo?
- 20. fusione dell'operatore - const vs non-const
- 21. Perché non c'è to_string (const string &)?
- 22. Membri privati: Statico const vs. just const
- 23. Un costruttore di spostamenti deve prendere un riferimento const o non const?
- 24. Perché operator ++ restituisce un valore non const?
- 25. C: Assegnazione di "static const char * const" a "static const char *"
- 26. riferimento const può essere assegnato un int?
- 27. Perché devi fornire la parola chiave const in operatore sovraccarica
- 28. È "auto const" e "const auto" uguali?
- 29. Converti const char * in const wchar_t *
- 30. Perché zumero_sync deve essere chiamato più volte?
Sto sperando in una citazione da The Standard qui, dal momento che non sono mai riuscito a convincermi che * * richiede il 'const'. (Osservando 12.2 p4 e 5 in N3936). – BoBTFish
In modo che il compilatore non debba verificare che nessun percorso modifichi il temporaneo prima che l'oggetto esca dall'ambito. –
@BoBTFish: stai osservando la durata dei temporaries legati ai riferimenti. Per le regole su come vincolarli, vedere [dcl.init.ref] (8.5.3 in C++ 11). In particolare, il punto finale di p5: "il riferimento deve essere un riferimento di lvalue a un tipo non volatile ** const ** [o] un riferimento di valore." –