Prüfen, ob zwei Referenzen sich auf das selbe Objekt beziehen
-
Hallo,
die Überschrift beschreibt mein Problem schon ganz genau. Bisher habe ich diesen Ansatz, der den Adressoperator verwendet:
template<typename T> bool are_equal(T &x, T &y){ return (&x == &y); } int main(){ int a,b; int &c(a); std::cout<< are_equal(a,a) // soll true sein << " " << are_equal(a,b) // soll false sein << " " << are_equal(a,c) // soll true sein << std::endl; }Das funktioniert auch wie gewünscht, aber ich habe zwei kleine Bedenken:
-
Bisher habe ich noch nie wirklich mit dem Adressoperator gearbeitet, das ganze klingt als ob es ziemlich nahe an der Hardware ist. Gibt es da irgendwelche Fallstricke an die ich nicht gedacht habe?
-
Den Adressoperator kann man ja auch überladen, wodurch die Funktion nicht mehr funktionieren könnte. In meinem Fall wird das nicht vorkommen, weil ich alleine an dem Projekt arbeite und das entsprechend vermeiden werde. Aber aus Interesse: Fällt jemandem eine bessere Lösung ein, die dieses Problem vermeidet?
-
-
SeppJ schrieb:
Das funktioniert auch wie gewünscht, aber ich habe zwei kleine Bedenken:
- Bisher habe ich noch nie wirklich mit dem Adressoperator gearbeitet, das ganze klingt als ob es ziemlich nahe an der Hardware ist. Gibt es da irgendwelche Fallstricke an die ich nicht gedacht habe?
Bedenken brauchst Du keine haben, dass ist gar nicht so nah an der Hardware wie Du vielleicht meinst, sondern es ist vielmehr eine Definition, dass zwei Pointer mit identischen Typ auch auf das identische Objekt zeigen, wenn sie gleich sind. Es geht sogar so was:
#include <iostream> using namespace std; struct Base1 { virtual ~Base1() {} int m_dummy1; }; struct Base2 { virtual ~Base2() {} int m_dummy2; }; struct Foo : Base1, Base2 { int m_x; }; int main () { Foo a; Base1* p1 = &a; Base2* p2 = &a; if( (void*)p1 != (void*)p2 ) cout << "beide Pointer sind verschieden " << endl; if( p1 == dynamic_cast< Base1* >( p2 ) ) cout << ".. zeigen aber auf das identische Objekt" << endl; return 0; }Ich würde die Funktion aber eher are_identical nennen - das ist ja der Unterschied: gleich <-> identisch.
SeppJ schrieb:
- Den Adressoperator kann man ja auch überladen, wodurch die Funktion nicht mehr funktionieren könnte. In meinem Fall wird das nicht vorkommen, weil ich alleine an dem Projekt arbeite und das entsprechend vermeiden werde. Aber aus Interesse: Fällt jemandem eine bessere Lösung ein, die dieses Problem vermeidet?
Wenn der Adressoperator überladen ist, so sollte er auch ein sinnvolles Ergebnis liefern. D.h. die Funktion liefert das 'richtige' Ergebnis - im Sinne der Überladung.
Gruß
Werner
-
Werner Salomon schrieb:
Bedenken brauchst Du keine haben, dass ist gar nicht so nah an der Hardware wie Du vielleicht meinst, sondern es ist vielmehr eine Definition, dass zwei Pointer mit identischen Typ auch auf das identische Objekt zeigen, wenn sie gleich sind.
Ausgezeichnet! Wenn das die Definition ist, ist es ja ganz genau so wie ich es will.
-
SeppJ schrieb:
Bisher habe ich noch nie wirklich mit dem Adressoperator gearbeitet, das ganze klingt als ob es ziemlich nahe an der Hardware ist. Gibt es da irgendwelche Fallstricke an die ich nicht gedacht habe?
Mir fallen im Moment zwei ein, die aber etwas an den Haaren herbeigezogen sind:
struct X { int i; operator int&() {return i;} }; struct Y : public X { int& ri; Y(X& other) : ri(other.i) { i = other.i; } operator int&() {return ri;} }; int main() { X x; int& ri = x.i; std::cout << are_equal<int>(ri, x) << std::endl; //true, trotz verschiedener Typen std::cout << are_equal<int>(x, y) << std::endl; //mal true, std::cout << are_equal<X>(x, y) << std::endl; //mal false... }- Den Adressoperator kann man ja auch überladen, wodurch die Funktion nicht mehr funktionieren könnte. In meinem Fall wird das nicht vorkommen, weil ich alleine an dem Projekt arbeite und das entsprechend vermeiden werde. Aber aus Interesse: Fällt jemandem eine bessere Lösung ein, die dieses Problem vermeidet?
Den Adressoperator zu überladen ist selten eine gute Idee, wenn dadurch nicht die ursprüngliche Semantik gewahrt wird. Und die beinhaltet nunmal, bei ein und demselben Objekt den selben Wert zurückzugeben.
-
SeppJ schrieb:
- Den Adressoperator kann man ja auch überladen, wodurch die Funktion nicht mehr funktionieren könnte. In meinem Fall wird das nicht vorkommen, weil ich alleine an dem Projekt arbeite und das entsprechend vermeiden werde. Aber aus Interesse: Fällt jemandem eine bessere Lösung ein, die dieses Problem vermeidet?
Programmierer, die den Adressoperator überladen, stehen meist auf der dunklen Seite der Macht.
Für diese Fälle haben die Jedis
boost::addressofentwickelt.
Die Sache hängt also von deinem Vertrauen ab.