zeiger vergleichen
-
vlad_tepesch schrieb:
ich habe mehrere Zeiger und möchte wissen, ob sie auf das Selbe objekt zeigen.
Ein Kollege meinte, dass es laut C++ Standard nicht spezifiziert sei, dass 2 Zeiger, die auf das gleiche objekt zeigen auch den selben Inhalt haben müssen.
Was meinst Du mit "Inhalt"? Die interne Repräsentierung eines Zeigers ist hier uninteressant.
Wenn Du zwei Zeiger vom Typ T* hast, dann kannst Du sie natürlich vergleichen.
Was stattdessen nicht immer funktioniert ist Zeiger-Arithmetik. Wenn zwei Zeiger voneinander subtrahiert werden, müssen sie in das gleiche Array gezeigt haben (dazu zählt auch das "Element" hinter dem letzten Element, man darf diesen Zeiger nur nicht dereferenzieren). Für die andere Richtung gilt das genauso. Wenn Du zu einem Zeiger eine Zahl addierst, so dass das Ergebnis vor das erste Element oder hinter das "Element" hinter dem letzten Element des Arrays zeigen würde => UB (undefined behaviour, undefiniertes Verhalten).
Vergleichen kannst Du aber ohne Probleme und so ein Vergleich verhält sich genauso, wie man das erwartet.
vlad_tepesch schrieb:
Es gibt ja mehrere Scenarien
simper Datentyp mit normalen Zeigern auf denselben
abgeleiteter Datentyp - beide Zeiger auf selbe Klasse der Vererbungshierarchie
abgeleiteter Datentyp - Zeiger auf verschiedene Klassen der Vererbungshierarchie
abgeleiteter polymorpher Datentyp - beide Zeiger auf selbe Klasse der Vererbungshierarchie
abgeleiteter polymorpher Datentyp - Zeiger auf verschiedene Klassen der Vererbungshierarchie...kannst Du alles munter vergleichen.
vlad_tepesch schrieb:
Edit:
Dann gibts ja auch noch Mehrfachvererbungen und zeiger, die auf Klassen verschiedener Zweige der selben oder unterschiedlicher Hierarchiestufen zeigen können....kannst Du alles munter vergleichen.
Gruß,
SP
-
Sebastian Pizer schrieb:
Wenn Du zwei Zeiger vom Typ T* hast, dann kannst Du sie natürlich vergleichen.
Ich möchte dies ein wenig präzisieren. Ich weiss nicht, ob es dir bewusst ist oder nicht, aber man kann höchstens immer zwei Zeiger auf Gleichheit prüfen. Wenn du vergleichen willst mit den Operatoren <, >, <= und >= dann musst du nochmals ein paar Dinge beachten.
Ich glaube, dass ich da am besten den Standard zitiere:
C++ Standard 14882:2003 - 5.9 Relational operators schrieb:
...
Pointers to objects or functions of the same type (after pointer conversions) can be com-
pared, with a result defined as follows:
— If two pointers p and q of the same type point to the same object or function, or both point one past the
end of the same array, or are both null, then p<=q and p>=q both yield true and p<q and p>q both
yield false.
— If two pointers p and q of the same type point to different objects that are not members of the same
object or elements of the same array or to different functions, or if only one of them is null, the results
of p<q, p>q, p<=q, and p>=q are unspecified.
— If two pointers point to nonstatic data members of the same object, or to subobjects or array elements of
such members, recursively, the pointer to the later declared member compares greater provided the two
members are not separated by an access-specifier label (11.1) and provided their class is not a union.
— If two pointers point to nonstatic data members of the same object separated by an access-specifier label
(11.1) the result is unspecified.
— If two pointers point to data members of the same union object, they compare equal (after conversion to
void*, if necessary). If two pointers point to elements of the same array or one beyond the end of the
array, the pointer to the object with the higher subscript compares higher.
— Other pointer comparisons are unspecified.@SWW13,
So eine Testreihe ist ziemlich sinnlos, da viele Dinge, auch bei Zeigern,Implementation definied
sind, also von Kompiler zu Kompiler unterschiedlich sein können.@vlad_tepesch,
1. Es gibt noch viel mehr Szenarien.
2. Was verstehst du unter Inhalt und Objekt? Wann zeigen für dich zwei Zeiger auf das gleiche Objekt? Was ist das gleiche Objekt?Grüssli
-
vlad_tepesch schrieb:
Ein Kollege meinte, dass es laut C++ Standard nicht spezifiziert sei, dass 2 Zeiger, die auf das gleiche objekt zeigen auch den selben Inhalt haben müssen.
ich denke, er spielt auf die hölle der mehrfachen erblichkeit an.
mal eine basisklasse Boot nehmen, davon virtuell Motorboot und Segelboot ableiten und von beiden den Motorsegler. dann einen Motorsegler anlegen und mal einen Boot*, einen Motorboot*, einen Segelboot* und einen Motorsegler* anlegen, die alle auf das selbe Objekt zeigen. dann die ganzen Objektzeiger mit cout ausgeben und vergleichen. ich hab's zwar noch nie gemacht, aber wenn ich mich recht erinnere, liegt hier ein hund begraben.
wenn du das mal kurz machen würdest und die ausgabe zeigen, würdest du mich diesbezüglich sehr erleuchten. (zur sicherheit dem boot das attribut double masse und den beiden erben je ein attribut geschwindigkeit geben.)
-
Die Frage bei Mehrfachvererbung ist aber, ob ein Zeiger auf ein Motorboot Objekt und ein Zeiger auf ein Segelboot Objekt auf das gleiche Objekt zeigen, wenn das ursprüngliche Objekt ein Motorsegler war?
Meiner Meinung nach nämlich nicht. Sie zeigen schliesslich nicht mehr auf das Motorsegler Objekt, sondern auf zwei unterschiedliche.Grüssli
-
#include <iostream> class Boot { protected: double masse; }; class Segelboot : public Boot { protected: double geschw; }; class Motorboot : public Boot { protected: double geschw; }; class Motorsegelboot : public Segelboot, public Motorboot { }; int main() { Motorsegelboot msb; Motorsegelboot *msbp = &msb; Motorboot *mbp = &msb; Segelboot *sbp = &msb; std::cout << msbp << std::endl; std::cout << mbp << std::endl; std::cout << sbp << std::endl; return 0; }
Ausgabe:
0x22ff50
0x22ff60
0x22ff50Ein Boot* kann nicht auf einen Motorsegelboot* zeigen.
(Ich kenne mich mit Mehrfachvererbung nicht so gut aus aber zumindest meckert der GCC.)
-
blub² schrieb:
Ein Boot* kann nicht auf einen Motorsegelboot* zeigen.
(Ich kenne mich mit Mehrfachvererbung nicht so gut aus aber zumindest meckert der GCC.)Sicher geht das, der GCC weiss wahrscheinlich bei deinem Code nur nicht, auf welches Boot er zeigen soll, da in deinem Motorsegelboot zwei enthalten sind. Deshalb solltest du, wie volkard gesagt hat, auch virtuell erben:
class Segelboot : virtual public Boot // <- { protected: double geschw; }; class Motorboot : virtual public Boot // <- { protected: double geschw; };
Wieso übrigens
protected
Memberdaten? Ganz schlechter Stil :pGrüssli
-
0x22ff40
0x22ff50
0x22ff40
0x22ff60#include <iostream> class Boot { protected: double masse; }; class Segelboot : virtual public Boot { protected: double geschw; }; class Motorboot : virtual public Boot { protected: double geschw; }; class Motorsegelboot : public Segelboot, public Motorboot { }; int main() { Motorsegelboot msb; Motorsegelboot *msbp = &msb; Motorboot *mbp = &msb; Segelboot *sbp = &msb; Boot *bp = &msb; std::cout << msbp << std::endl; std::cout << mbp << std::endl; std::cout << sbp << std::endl; std::cout << bp << std::endl; return 0; }
Wieso übrigens protected Memberdaten? Ganz schlechter Stil :p
Mache ich normal nicht, war nur das erste was mir die Vervollständigung von Code::Blocks angeboten hat :D.
-
Keine Ahnung, was ihr mit den Codebeispielen erreichen wollt. So wie ich das sehe, kann man die Identitaet von Objekten anhand von Zeigern nur feststellen, wenn sie vom gleichen Typ sind, d.h. alles zur Basisklasse casten und dann erst vergleichen (notfalls zu void*).
-
Sorry, hatte gestern keine Zeit mehr.
0x22ff40
0x22ff50
0x22ff40
0x22ff60Das heißt, ich kann durch Zeigervergleich tatsächlich nicht feststellen, ob es sich um das selbe objekt handelt.
@vlad_tepesch,
1. Es gibt noch viel mehr Szenarien.
2. Was verstehst du unter Inhalt und Objekt? Wann zeigen für dich zwei Zeiger auf das gleiche Objekt? Was ist das gleiche Objekt?Sich er, dass waren die mir spontan eingefallen sind.
Inhalt eines zeigers ist die Adresse auf die er Zeigt.
Mit gleichem objekt meine ich das selbe ObjectIch habe 2 Zeiger und möchte wissen, ob sie auf das selbe Object zeigen.
in meinem Fall sind die Zeiger gleichen Typs, sowie die Objecte auf die sie zeigen auch
Da sollte es scheinbar keine Probleme geben.class A{ Paar* pPaar; }; class B:public A class Paar { A* pa1; A* pa2; } A* myP = new B;
Ich hole mir ein aus myP den pointer auf Paar und daraus das pPaar des anderen A*
(wenn myP = myP->pPaar->pa1 == myP, dann pp2 = myP->pPaar->pa1->pc sonst pp2 = myP->pPaar->pa2->pc)
Dann möchte ich schauen, ob die auf das selbe Paar zeigen.Das ganze ist Teil einer komplizierten Listenstruktur.
eine Liste enthält alle As.
eine andere alle Paare.
ein A, kann in mehreren Paaren vorkommen.
der Zeiger in A zeigt immer auf das beste Paar. (das ist redundant, verhindert aber das viele suche in den Listen, da das beste Paar sehr häufig gebraucht wird)
an einer stelle möchte ich feststellen, ob der Partner des untersuchten A auch das untersuchte A als besten Partner hat.Keine Ahnung, was ihr mit den Codebeispielen erreichen wollt. So wie ich das sehe, kann man die Identitaet von Objekten anhand von Zeigern nur feststellen, wenn sie vom gleichen Typ sind, d.h. alles zur Basisklasse casten und dann erst vergleichen (notfalls zu void*).
glaub nicht, dass ein Cast zu void was an der Adresse ändert, auf die der Zeiger zeigt.
-
vlad_tepesch schrieb:
...Das heißt, ich kann durch Zeigervergleich tatsächlich nicht feststellen, ob es sich um das selbe objekt handelt....
... oder Du überdenkst, was Du unter "dasselbe Objekt" verstehst.
Die Frage ist IMHO nicht so trivial wie sie auf den ersten Blick scheint. Vielleicht könnte man sogar andersherum definieren: "Zwei Zeiger zeigen genau dann auf dasselbe Objekt, wenn sie denselben Wert haben"
Wäre eine mögliche Definition ... eine andere (durchaus auch mit Existenzberechtigung, eher durch den Begriff des "Fachobjekts" geprägt) ist:
"Es handelt sich genau dann um dasselbe Objekt, wenn der operator==() true zurückliefert."
gibt bestimmt noch mehr ...Gruß,
Simon2.
-
... durch Zeigervergleich tatsächlich nicht feststellen ...
Aber nur, weil die Zeiger nicht vom gleichen Typ sind.
Es handelt sich genau dann um dasselbe Objekt, wenn der operator==() true zurückliefert.
Nein, da ich selbst operator==() mit Semantik belegen kann. Auch ist 5 == 5, aber 5 kann an unterschiedlichen Stellen gespeichert sein, so dass es sich nicht um das selbe Objekt handelt, nur um das gleiche. Spielt das eine Rolle? Ja!
-
blub² schrieb:
#include <iostream> class Boot { protected: double masse; }; class Segelboot : public Boot { protected: double geschw; }; class Motorboot : public Boot { protected: double geschw; }; class Motorsegelboot : public Segelboot, public Motorboot { }
Hier sollte außerdem virtuelle Vererbung benutzt werden, da man sonst 2 Isntanzen der Klasse Boot in Motorsegelboot hat.
class Boot { double masse; double geschw; }; class Segelboot : virtual public Boot { int masten; }; class Motorboot : virtual public Boot { int ps; }; class Motorsegelboot : virutal public Segelboot, virtual public Motorboot { }
-
Simon2 schrieb:
"Es handelt sich genau dann um dasselbe Objekt, wenn der operator==() true zurückliefert."
Das ist der kleine, aber feine Unterschied zwischen 'das gleiche' und 'das selbe'
Wenn man sagt, "der hat das selbe Hemd an, wie ich.", dann ist das unmöglich (wenn man mal Viele-Welten-Theorien weglässt ;)).
-
vlad_tepesch schrieb:
Sorry, hatte gestern keine Zeit mehr.
0x22ff40
0x22ff50
0x22ff40
0x22ff60Das heißt, ich kann durch Zeigervergleich tatsächlich nicht feststellen, ob es sich um das selbe objekt handelt.
Klar kannst Du. Du darfst Dich nur nicht auf die textuelle Repräsentierung eines nach void* konvertierten Zeigers verlassen, die Du über operator<<(ostream&,void*) bekommst. Eine Konvertierung eines Zeigers in einen anderen Typen (deren Klassen in einer Vererbungsbeziehung stehen) kann die interne Repräsentierung ändern. Das, was Dir std::cout da anzeigt ist völlig uninteressant. Beispiel:
#include <iostream> class A {int a;}; class B {int b;}; class C : A, B {}; int main() { C c; A* pa = &c; B* pb = &c; C* pc = &c; std::cout << pa << '\n'; std::cout << pb << '\n'; std::cout << pc << '\n'; std::cout << (pa==pc) << '\n'; std::cout << (pb==pc) << '\n'; }
Hier ist zu erwarten, dass die ersten drei Ausgaben nicht gleich sind, da
pa
undpb
auf die "Sub-Ojekte" vonc
zeigen und die natürlich nicht an der gleichen Stelle im Speicher stehen. Trotzdem liefert die Vergleichsoperation in beiden Fällen 1, weilpc
jeweils implizit zu A* bzw B* konvertiert und damit eventuell angepasst wird.Bei mir bekomme ich folgendes Ergebnis:
0x22ff70 0x22ff74 0x22ff70 1 1
I rest my case.
Gruß,
SP
-
knivil schrieb:
Es handelt sich genau dann um dasselbe Objekt, wenn der operator==() true zurückliefert.
Nein, da ich selbst operator==() mit Semantik belegen kann.
Was natürlich gemeint war: Wenn ein Zeigervergleich (==)
true
liefert, dann zeigen sie auf das selbe Objekt (oder der eine zeigt auf ein Sub-Objekt des anderen). Das Überladen von operator== bei Zeigern ist nicht möglich.Gruß,
SP
-
knivil schrieb:
...
Es handelt sich genau dann um dasselbe Objekt, wenn der operator==() true zurückliefert.
Nein, da ich selbst operator==() mit Semantik belegen kann....
Eben - genau deswegen.
Es ist einfach eine andere Defintion dessen, welche Unterschiede interessieren - und welche eben nicht.
Die "Zeigerdefinition" ist auch nicht so "unantastbar", wie es auf den ersten Blick scheint. So können Betriebssysteme durchaus zu unterschiedlichen Zeitpunkten Speicheradressen auf unterschiedliche "physikalische" Speicheradresse abbilden (bis hin zum Swapping auf Platte) ... oder von unterschiedlichen (auch parallelen) Prozessen dieselben Anwendungsadressräume auf unterschiedliche "physikalische".
Hin bis zu der Frage, ob es sich um dasselbe Objekt handelt, wenn es durch den Stromfluss anderer Elektronen in der Elektronik abgebildet wird.
(wobei auch die Frage nach "demselben Elektron" ebenso spannend ist)Es ist immer die Frage: Welche Aspekte lasse ich unter den Tisch fallen...
Gruß,
Simon2.
-
vlad_tepesch schrieb:
...Das ist der kleine, aber feine Unterschied zwischen 'das gleiche' und 'das selbe'...
Nunja, diese beiden Ausdrücke sind aber nicht so streng definiert (oder gar gegeneinander abgegrenzt), dass man sie ohne weitere Erklärung verwenden oder zuordnen kann.
"Das selbe" drückt zwar den Versuch aus, möglichst viele Übereinstimmungen zu finden, während "das gleiche" mehr Raum lässt für Abweichungen - aber auch das üblicherweise nur im direkten Gegensatz. Wenn ich also zurückfrage "Dasselbe oder das Gleiche?" will ich genau auf die "Einschränkungen"/"Unterschiede" hinaus ... wenn ich dagegen eines von beiden verwende, betont man üblicherweise nur die Gemeinsamkeiten.In Diskussionen kann es sehr hilfreich sein, diese beiden Begriffe bewusst (und auf den jeweiligen Kontext hin definiert) zu verwenden, aber allgemeingültig klären sie IMHO das Problem nicht.
Mal eine kleine Gegenfrage: Bist Du nach Lesen dieses Posts noch derselbe wie davor?
Gruß,
Simon2.
-
Jetzt wird's philosophisch. Die deutsche Sprache ist nicht exakt und kann so nicht auf Computersprachen abgebildet werden. Was im Hintergrund laeuft a la swapping oder tatsaechliche physikalische Speicherbereiche ist nebensachlich, da es sauber vom Betriebssystem gekapselt wird (fuer gewoehnlich). Auch ueber Elektronen sagt der C++ Standard nichts aus.
Bist Du nach Lesen dieses Posts noch derselbe wie davor?
Im Sinne von C++ ja. Aber hier fuehrst du etwas neues ein: vorher und nachher.
-
knivil schrieb:
Jetzt wird's philosophisch. ...
Japp - das ist aber auch immer der interessantere Teil.
knivil schrieb:
...Was im Hintergrund laeuft a la swapping oder tatsaechliche physikalische Speicherbereiche ist nebensachlich, da es sauber vom Betriebssystem gekapselt wird (fuer gewoehnlich). Auch ueber Elektronen sagt der C++ Standard nichts aus...
Aber auch nichts darüber, was "dasselbe Objekt" sei.
Deshalb sehe ich nicht, wo ein "Zeigervergleich" C++iger sei als ein "operator==()"-Vergleich.knivil schrieb:
...Aber hier fuehrst du etwas neues ein: vorher und nachher.
Naja, sooo neu ist das im Zusammenhang mit Objektvergleichen nicht, denn es ist doch eher der absolute Ausnahmefall, dass 2 zu vergleichende Referenzen exakt zum selben Zeitpunkt erzeugt wurden.
Auch wenn ich von Dir spreche mit Jemandem, der Dich gestern gesehen hat, wird die Frage sein, ob wir von demselben sprechen.
Gruß,
Simon2.
-
vlad_tepesch schrieb:
Mit gleichem objekt meine ich das selbe Object
Frage ist nicht beantwortet. Mir geht es um dasselbe Objekt im Speicher oder dasselbe polymorphe Objekt.
Ein wenig Code zur Vedeutlichung:
#include <iostream> struct Base { virtual ~Base() { } // für dynamic_cast char dummy; }; struct DLeft : Base { char dummy; }; struct DRight : Base { char dummy; }; struct DCenter : DLeft, DRight { char dummy; }; int main() { DCenter c; Base* bl = static_cast<DRight*>(&c); Base* br = static_cast<DLeft*>(&c); std::cout << (bl == br) << std::endl; DCenter* cl = dynamic_cast<DCenter*>(bl); DCenter* cr = dynamic_cast<DCenter*>(br); std::cout << (cl == cr) << std::endl; return 0; }
Da können nicht mal mehr Leute was dagegen sagen, welche verlangen, dass die beiden Zeiger vom gleichen Typ sind
Die erste Ausgabe ist 0, es sind zwei unterschiedliche Base Objekte, auf welche die Zeiger verweisen. Das polymorphe Objekt ist allerdings dasselbe, wie es die zweite Ausgabe nochmals verdeutlicht.Grüssli