Wenn ich kompilieren den folgenden Code g++
Referenz-Konvertierungsoperatoren: Fragen nach Ärger?
class A {};
void foo(A&) {}
int main()
{
foo(A());
return 0;
}
Ich bekomme die folgende Fehlermeldung mit:
> g++ test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:10: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’
test.cpp:6: error: in passing argument 1 of ‘void foo(A&)’
Nach einigem Nachdenken, diese Fehler viel Sinn für mich. A()
ist nur ein temporärer Wert, kein zuweisbarer Speicherort auf dem Stapel, daher scheint es keine Adresse zu haben. Wenn es keine Adresse hat, kann ich keinen Hinweis darauf halten. Okay gut.
Aber warte! Wenn ich den folgenden Konvertierungsoperator die Klasse A
class A
{
public:
operator A&() { return *this; }
};
hinzufügen
dann ist alles gut! Meine Frage ist, ob dies auch nur annähernd sicher ist. Was genau zeigt this
auf, wenn A()
als temporärer Wert erstellt wird?
Ich bin etwas Vertrauen durch die Tatsache gegeben, dass
void foo(const A&) {}
temporäre Werte nach g++
und alle anderen Compilern akzeptieren kann ich benutzt habe. Das const
Schlüsselwort kann immer weggeworfen werden, so würde es mich überraschen, wenn es irgendwelche tatsächlichen semantischen Unterschiede zwischen einem const A&
Parameter und einem A&
Parameter gäbe. Also denke ich, dass das eine andere Art ist, meine Frage zu stellen: Warum ist ein const
Verweis auf einen temporären Wert, der vom Compiler als sicher betrachtet wird, während ein nicht-const
Verweis nicht?
Ich stimme zu, dass diese Art von Sache normalerweise ein Programmierfehler ist. Für den Fall, dass Sie neugierig sind, ist die Klasse, die ich als Referenz übergeben möchte, eine Art intelligenter Zeiger, dem ein zugrunde liegendes Heap zugewiesenes Zeigerelement zugeordnet ist. Ich möchte tatsächlich, dass die Empfangsfunktion Dinge mit dem zugrunde liegenden Zeiger ausführt. Ich möchte nur sicher sein, dass der temporäre Smart-Zeiger nicht zerstört wird (Dekrementieren der Referenzzählung), bis die Empfangsfunktion zurückkehrt. – Ben
Wenn dies Ihre Absicht ist, deklarieren Sie entweder den Smart Pointer explizit auf dem Stack, übergeben ihn oder übergeben ihn wertmäßig. Wenn Sie sie als Wert übergeben, ist sichergestellt, dass sie nicht zerstört wird, bis die Funktion beendet wird. – MSN
@Ben - hinzugefügt einige zu meinem Beitrag darüber. Kann nicht sagen, ob es eine gute Idee für Sie ist, ohne Ihren Code zu sehen, aber es gibt einige Anwendungsfälle (und es wird nicht zerstört, bis es zurückkehrt) –