Implizite Konvertierung: const Referenz vs nicht konstante Referenz vs Nicht-Referenz
-
11-10-2019 - |
Frage
Betrachten Sie diesen Code,
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);
}
Der compiles feine , läuft gut. Aber wenn ich Änderung f(B)
zu f(B&)
, es nicht kompilieren . Wenn ich f(const B&)
schreiben, wieder es feinen kompiliert, läuft gut. Warum ist der Grund und Begründung?
Zusammenfassung:
void f(B); //okay
void f(B&); //error
void f(const B&); //okay
Ich mag Gründe hören, Begründung und Referenz (en) aus der Sprachspezifikation, für jeden dieser Fälle. Natürlich sind die Funktionssignaturen selbst nicht falsch. Vielmehr A
implizit konvertiert in B
und const B&
, aber nicht in B&
, und das bewirkt, dass der Übersetzungsfehler.
Lösung
Ich mag Gründe hören, Begründung und Referenz (en) aus der Sprachspezifikation
Ist The Design und Entwicklung von C ++ ausreichend?
ich einen schweren Fehler gemacht, aber durch eine nicht konstante Referenz ermöglicht durch einen nicht-L-Wert initialisiert werden [ Kommentar von mir: Diese Formulierung ist ungenau !]. Zum Beispiel:
void incr(int& rr) { ++rr; } void g() { double ss = 1; incr(ss); // note: double passed, int expected // (fixed: error in release 2.0) }
Aufgrund der Unterschiede in Art kann der
reflektiertint&
nicht auf diedouble
weitergegeben verweisen so eine temporäre generiert wurde einint
vonss
Wert initialisiert zu halten. So modifizierteincr()
die temporäre und das Ergebnis wurde nicht zurück an die anrufende Funktion [ Hervorhebung von mir ].
Denken Sie daran: Der ganze Sinn der Call-by-Referenz ist, dass der Client übergibt Dinge, die durch die Funktion geändert werden, und nachdem die Funktion zurückkehrt, muss der Kunde in der Lage sein, um die Änderungen zu beobachten .
Andere Tipps
Das Problem besteht darin, daß die implizite Umwandlung von einem Objekt zu einem B ergibt einen R-Wert. Nicht konstante Referenzen können nur an lvalues ??binden.
Wenn B einen Standardkonstruktor hat würden Sie das gleiche Verhalten, wenn Sie den f(a)
Aufruf f(B())
ändern.
-
litb bietet eine große Antwort auf das, was ein L-Wert: Stack-Überlauf - häufig verwendet selten definierte Begriffe: L-Wert
GOTW # 88: ein Kandidat für den „wichtigsten const“
Stack-Überlauf - Wie kommen eine nicht konstante Referenz auf ein temporäres Objekt nicht binden?
-
Um mit Verweisen auf den Standard zu erklären, wie diese Funktionsaufrufe scheitern oder gelingen übermäßig lange wären. Das Wichtigste ist, wie B& b = a;
ausfällt, während const B& b = a;
nicht ausfällt.
(vom Entwurf n1905)
A reference „CV1 T1“ zu geben, indem ein Ausdruck des Typs initialisiert „CV2 T2“ wie folgt:
- [ ein L-Wert ist und entweder Referenz kompatibel oder implizit konvertierbar zu einem L-Wert einer Referenz kompatibelen Typs ... ]
-. Andernfalls ist die Bezugnahme auf einen nichtflüchtigen const Typ sein (das heißt, wird sein CV1 const)
Hier einen Fall, wo etwas zu einem L-Wert von Referenz kompatibelen Typ konvertierbar ist.