La conversione implicita: riferimento const vs riferimento non-const vs non-reference
-
11-10-2019 - |
Domanda
Si consideri questo codice,
struct A {};
struct B { B(const A&) {} };
void f(B)
{
cout << "f()"<<endl;
}
void g(A &a)
{
cout << "g()" <<endl;
f(a); //a is implicitly converted into B.
}
int main()
{
A a;
g(a);
}
compila bene , funziona benissimo. Ma se cambio f(B)
a f(B&)
, è non viene compilato . Se scrivo f(const B&)
, di nuovo compila bene , funziona benissimo. Perché è la ragione e la logica?
Sommario:
void f(B); //okay
void f(B&); //error
void f(const B&); //okay
Mi piacerebbe sentire ragioni, delle motivazioni e riferimento (s) dal specifica del linguaggio, per ciascuno di questi casi. Naturalmente, le firme di funzione stessi non sono corretti. Piuttosto A
implicitamente si trasforma in B
e const B&
, ma non in B&
, e che causa l'errore di compilazione.
Soluzione
Mi piacerebbe sentire ragioni, delle motivazioni e riferimento (s) dal specifica del linguaggio
Il design e l'evoluzione del C ++ è sufficiente?
ho fatto un grave errore, però, consentendo un riferimento non const da inizializzare da un non lvalue [ commento di me: tale formulazione è imprecisa !]. Ad esempio:
void incr(int& rr) { ++rr; } void g() { double ss = 1; incr(ss); // note: double passed, int expected // (fixed: error in release 2.0) }
A causa della differenza nel tipo il
int&
non può fare riferimento al passatodouble
modo temporaneo è stato generato per contenere unint
inizializzato al valore diss
. Così,incr()
modificato il temporanea, e il risultato non si è riflessa indietro alla funzione di chiamata ??strong> [ sottolineatura mia ].
Pensateci: Il punto di chiamata per riferimento è che il client passa le cose che vengono modificate dalla funzione, e dopo la funzione ritorna, il cliente deve essere in grado di osservare i cambiamenti .
Altri suggerimenti
Il problema è che la conversione implicita da una a un oggetto B produce una rvalue. riferimenti non-const possono legarsi solo per lvalue.
Se B ha avuto un costruttore di default si otterrebbe lo stesso comportamento se si cambia la chiamata f(a)
a f(B())
.
-
litb fornisce una grande risposta a ciò che è un lvalue: Stack Overflow - spesso utilizzati termini raramente definiti: lvalue
GotW # 88: un candidato per il “Most const importante”
Stack Overflow - Come mai un riferimento non-const non può legarsi ad un oggetto temporaneo?
-
Per spiegare con riferimenti alla norma come quei chiamate di funzione o non riescono ad avere successo sarebbe eccessivamente lungo. La cosa importante è come B& b = a;
fallisce mentre const B& b = a;
non fallisce.
(da progetto n1905)
Un riferimento a tipo “CV1 T1” viene inizializzato da un'espressione di tipo “cv2 T2” come segue:
- [ è un lvalue ed è uno di riferimento compatibile o implicitamente convertibile in un lvalue di un tipo compatibile di riferimento ... ]
-. In caso contrario, il riferimento deve essere di tipo const non volatile (cioè, CV1 è const)
Ecco un caso in cui qualcosa è convertibile ad un lvalue di tipo compatibile di riferimento.