Ist diese statische C ++ - Analyseregel so sinnvoll wie sie ist?
Ich implementiere einige statische C ++ - Analyseregeln, und eine von ihnen verhindert, dass eine Funktion eine Referenz oder einen Zeiger auf einen Referenzparameter der Funktion zurückgibt, d. H. Die folgenden Regeln sind alle nicht konform:
int *f(int& x) { return &x; } // #1
const int *g(const int& x) { return &x; } // #2
int& h(int& x) { return x; } // #3
const int& m(const int& x) { return x; } // #4
Die Begründung hierfür lautet: "Es ist ein implementierungsdefiniertes Verhalten, ob der Referenzparameter ein temporäres Objekt oder ein Verweis auf den Parameter ist."
Das verwirrt mich jedoch, da Stream-Operatoren in C ++ auf diese Weise geschrieben sind, z.
std::ostream& operator<<(std::ostream& os, const X& x) {
//...
return os;
}
Ich bin mir ziemlich sicher, dass Stream-Operatoren in C ++ im Allgemeinen kein implementierungsdefiniertes Verhalten aufweisen. Was ist also los?
Nach meinem derzeitigen Verständnis würde ich erwarten, dass # 1 und # 3 gut definiert sind, auf der Grundlage, dass Provisorien nicht an nicht konstante Referenzen gebunden werden könnenint& x
Bezieht sich auf ein reales Objekt, dessen Lebensdauer über den Funktionsumfang hinausgeht. Die Rückgabe eines Zeigers oder einer Referenz auf dieses Objekt ist daher in Ordnung. Ich würde erwarten, dass # 2 zwielichtig ist, weil eine vorübergehende Bindung hätte bestehen könnenconst int& x
In diesem Fall scheint es ein schlechter Plan zu sein, seine Adresse zu übernehmen. Ich bin mir nicht sicher, was # 4 angeht - mein Bauchgefühl ist, dass das auch möglicherweise zweifelhaft ist, aber ich bin mir nicht sicher. Insbesondere ist mir nicht klar, was im folgenden Fall passieren würde:
const int& m(const int& x) { return x; }
//...
const int& r = m(23);