Vektoren, Iteratoren, Zeiger, Referenzen - hab mich wohl verheddert



  • Hallo zusammen,

    beim Zusammenbasteln meiner bestimmt viel zu komplizierten "Engine" von Klassen, Containern, Objekten usw. hab ich sicher jede Menge Design- und Handwerksfehler.

    Ein Bsp., bei dem ich aktuell nicht verstehe, wieso ich immer die gleiche Adresse im Logging bekomme ist Folgendes:

    Ich habe mir eine Klasse gebaut, welche eine Rechteckstruktur kapselt und einige read-only-Methoden für das Lesen anbietet. Darunter eine, welche einen konstanten Zeiger auf eine konstante Struktur zurück gibt (weiss grad nicht mehr, wieso ich sogar 3 Mal const da drin hab - habe aber damals gelesen und gelernt, dass das der Weg ist, einen unveränderlichen Zeiger auf ein unveränderliches Element zu bekommen. Den Zeiger brauche ich für unterliegende API-Funktionen des Betriebssystems. Das Ganze sieht so aus:

    class RectangleC
    {
    ...
        inline const struct Rectangle * const getRectangleStruct() const { return &rectangle; }
    

    Es wird die Adresse der gekapselten Rechteck-Struktur zurückgegeben, mit sämtlich möglicher Konstanz.

    So weit - so gut.

    Nun habe ich in einer anderen Klasse einen Vector von Zeigern auf diese Rechteckobjekte (von denen jedes so eine Struktur kapselt).
    Wenn ich nun über einen Iterator des Vektors laufe und mit die Zeiger auf die Rechteckobjekte geben lasse und diese aber als Referenz ansprechen möchte, mach ich das so:

    or (std::vector<RectangleC *>::iterator itProtectedAreas = protectedAreas.begin(); itProtectedAreas != protectedAreas.end(); itProtectedAreas++)
        	{
        	    RectangleC& protectedArea = (**itProtectedAreas);
    ...
    

    Nun lasse ich mir zur Kontrolle die Adresse des Objektes und der darin enthaltenen Adresse der Rechteck-Struktur ausgeben:

    std::cout << "ProtectedArea " << (&protectedArea) << " mit Rechteck " << (protectedArea.getRectangleStruct()) ...
    

    Interessanterweise bekomme ich 2 Mal die gleiche Adresse ausgegeben - aber wieso?
    Das Erste müsste doch die Adresse des Objektes sein, das 2. die Adresse der Struktur innerhalb des Objektes? Oder steh ich auf dem Schlauch?

    Interessanterweise passiert dasselbe schon im Konstruktor von RectangleC - hier bekomme ich auch 2 Mal dieselbe Adresse ausgegeben:

    class RectangleC
    {
        private:
            struct Rectangle rectangle;
            int width, height;
    
        public:
            RectangleC(...)
            {
    ...
                std::cout << "Erzeuge Rechteck " << this << " mit rectangle struct: " << &rectangle << std::endl;
    ...
    

    Aber wieso?

    Kann mir da jemand Licht ins Dunkel bringen?

    Danke schon mal!

    Ciao



  • Reth schrieb:

    Das Erste müsste doch die Adresse des Objektes sein, das 2. die Adresse der Struktur innerhalb des Objektes? Oder steh ich auf dem Schlauch?

    Ja, aber wo sollte die 2te Adresse denn sein?

    Klarer wird es vielleicht so:

    struct A
    {
    	int a;
    	int b;
    
    	A()
    	{
    		std::cout << this << " " << &a << " " << &b;
    	}
    };
    
    int main() {
            A a;
    	return 0;
    }
    


  • Steh immer noch auf dem Schlauch.

    Die erste Adresse würde ich für das Objekt erwarten (dort beginnt es im Speicher), die zweite für die in dem Objekt enthaltene Struktur. In meinem Bsp. hat jedes Objekt der Klasse RectangleC auch noch andere Member.


  • Mod

    Reth schrieb:

    In meinem Bsp. hat jedes Objekt der Klasse RectangleC auch noch andere Member.

    In deinem Beispiel ist nur ein Member. Wenn du dich auf nicht gezeigten Code beziehst, können wir nicht helfen. Üblicherweise werden die Basisklassen- und Membersubobjekte in der Reihenfolge der Deklaration angeordnet.
    Wenn keine Basisklasse vorhanden ist und nicht zuvor virtuelle Funktionen deklariert wurden, hat der erste nichtstatische Member typischerweise (vom Standard garantiert nur im Fall von Standardlayoutklassen) ein Offset von 0 relativ zum umgebenden Klasse, in diesem Fall sind Adressen des Klassenobjektes und des Members wie beobachtet gleich.



  • @Camper:
    Danke! Genau das hatte ich schon vermutet, allerdings auch nach längerem Bemühen von Google noch nix dazu gefunden! Ist das irgendwo beschrieben?

    Ja, das mit den anderen Membern hatte ich leider nicht im Bsp. (habs oben noch ergänzt):

    class RectangleC
    {
        private:
            struct Rectangle rectangle;
            int width, height;
    
        public:
    ...
    


  • struct Rectangle rectangle;
    

    Warum struct?



  • Reth schrieb:

    Genau das hatte ich schon vermutet, allerdings auch nach längerem Bemühen von Google noch nix dazu gefunden! Ist das irgendwo beschrieben?

    Im Zweifelsfall hilft eigentlich immer nur der Standard.

    open-std.org n3690, §9.2 (19) schrieb:

    If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member.

    Allerdings hätte ich das andersherum formuliert.



  • Danke Dir!



  • manni66 schrieb:

    struct Rectangle rectangle;
    

    Warum struct?

    Sorry, hatte ich übersehen. Die Struktur ist Teil des Betriebssystem-APIs, das ich verwende.



  • Reth schrieb:

    manni66 schrieb:

    struct Rectangle rectangle;
    

    Warum struct?

    Sorry, hatte ich übersehen. Die Struktur ist Teil des Betriebssystem-APIs, das ich verwende.

    Auch dann ist das struct in C++ nicht notwendig.



  • man muss das Schlüsselwort nicht mehr angeben, wenn man ein Variable dieses Typs deklariert?



  • Reth schrieb:

    man muss das Schlüsselwort nicht mehr angeben, wenn man ein Variable dieses Typs deklariert?

    In C++: Nein


Log in to reply