Die folgenden minimal-ish segfaults Programm, wenn es mit -O3
und vielleicht mit -O2
kompiliert, sondern führt mit -O0
(mit Klirren 4,0) fein:Detect oder tote Verweise auf temporäres vermeiden auf der Kompilierung
#include <iostream>
class A {
public:
virtual void me() const { std::cerr << "hi!\n"; }
};
class B {
public:
B(const A& a_) : a(a_) {}
virtual void me() const { a.me(); }
private:
const A& a;
};
class C {
public:
C(const B& b_) : b(b_) {}
void me() const { b.me(); }
public:
const B& b;
};
int main() {
C c = C(A());
c.me();
}
Der Grund ist, dass mit einem Verweis auf ein temporäres Objekt der Klasse B
initialisiert wird, das aus einem temporären A
besteht. Nachdem der Konstruktor c.C()
beendet wurde, ist das temporäre B
verschwunden, aber die Referenz darauf bleibt in .
Welche guten Praktiken kann ich verwenden, um diese Situation zu vermeiden, da ich die Implementierung von B
oder A
nicht kontrolliere? Gibt es statische Analysatoren, die diesen Zustand erkennen können? (Meine Version von scan-build
fand nicht das Problem.)
Verwandte: Detect dangling references to temporary
Nun, Sie jetzt, rvalue Referenzen. Sie binden nur an Provisorien. Ich denke, das kann vielleicht als Lvalue-only-ref-wrapper abstrahiert werden. –
Als allgemeine Regel deklarieren Sie keine Mitgliedsvariablen vom Typ reference. Verwenden Sie stattdessen einen Zeiger. Und wenn Sie einen Zeiger im Konstruktor bekommen, wird der resultierende Code offensichtlich sein. – rodrigo
@rodrigo: Das klingt interessant.Ich denke, es würde auch funktionieren, wenn ich das Konstruktorargument nur als Zeiger deklariere und dann die Referenz initialisiere? Ich würde lieber * all * des Codes, der die Referenz verwendet, nicht umschreiben ... – krlmlr