[AssignmentOp] PointerArray kopieren



  • Ich habe ein Array(matrix_) mit Pointers und einige Pointer davon sind NULL.
    Ich will nun in einem AssignmenOperator dieses Array, dass member einer Klasse ist kopieren.

    Jetzt habe ich folgendes Problem:

    //bm ist das argument des AssignmentOps
    if(bm.matrix_[i][j] != NULL)
        *matrix_[i][j]=*bm.matrix_[i][j]; //BOOM!
    else
        matrix_[i][j]=NULL;
    

    In der markierten Zeile knallts, weil natuerlich in einigen Faellen auf der linken Seite der Zuweisung verusucht wird ein NULL-Pointer zu dereferenzieren.
    Aber wie koennte ich die Werte aus der anderen Klasse sonst kopieren?
    Wie kann ich dieses Problem ohne eine dynamische Allokation loesen?

    thx in advance



  • Bin grad zu dem Schluss gekommen, dass ich um ein new statement wohl nicht herumkomme. Falls es doch geht, meldet euch.



  • Ich versuch noch mal von vorne anzufangen. Mich laesst das Problem nicht los.
    Hab mich jetzt doch wieder umentschieden.
    Folgendes Programmfragment:

    class Foo { };
    
    class Bar
    {
        Foo *f[10][10];
        //...
        Bar operator=(const Bar& src);
        //...
    };
    
    Bar operator=(const Bar& src)
    {
        for(int i=0; i<10; ++i)
            for(int j=0; j<10; ++j)
                if(src.f[i][j] != NULL)
                    *f[i][j]=*src.f[i][j];    //BOOM!
                else
                    f[i][j]=NULL;
    }
    

    Das Array Bar::f enthaelt auch NULL Pointer.
    Wie angedeutet knallts gelegentlich in der markierten Zeile, weil this->f[i][j]==NULL ist.
    Wie kann ich den operator= vernuenftig implementieren, ohne dass versucht wird NULL-Pointer zu dereferenzieren?



  • Das problem ist einfach das du versuchst daten auf einen Speicherbereich der dir gar nicht gehört zu zuweisen. Deine neue klasse braucht entweder einen neuen speicherbereich, den du wie du bereits erkannt hast mit new erstellen musst, oder du kopierst lediglich die Pointer, was zur Folge hat das das array auf die gleichen elemente zeigt.

    MfG



  • Das Problem resultiert doch aber nur daraus, dass NULL Pointer unter den zu kopierenden(src), bzw. noch enthaltenen(this) Elementen vorhanden sind, oder?
    Weil sonst koennte ich ja einfach die Pointer dereferenzieren und dann wuerden der CopyCtor von Foo das Kopieren uebernehmen koennen.

    *f[i][j]=*src.f[i][j];
    


  • Hier resultiert das Problem eher daher das die linke seite auf irgendwas zeigt, aber nicht auf einen Speicherplatz ( den er benutzen darf ). Die Rechte Seite kann wegen deiner Abfrage nicht NULL sein.

    *f[i][j]=*src.f[i][j];
    

    Btw. Wenn du platz für einen pointer hast, hast du noch lange nicht platz für ein objekt!



  • evilissimo schrieb:

    Hier resultiert das Problem eher daher das die linke seite auf irgendwas zeigt, aber nicht auf einen Speicherplatz ( den er benutzen darf ).

    *f[i][j]=*src.f[i][j];
    

    Wir reden hier vom operator= und nicht dem CopyCtor. Warum sollten die Pointer nicht auf einen Speicherplatz zeigen?

    Falls du jetzt meinst, dass einige auf NULL zeigen, dann hast du genau das wiederholt, was ich in meinem vorherigen Post geschrieben habe.



  • Ich meine das es gut sein kann das du gar keinen Speicherplatz hast auf den du was zuweisen kannst, davon rede ich. Zeig mir mal wie du das Array im Konstruktor initialisierst und ihm speicher zuweist.

    MfG



  • Raptor schrieb:

    evilissimo schrieb:

    Hier resultiert das Problem eher daher das die linke seite auf irgendwas zeigt, aber nicht auf einen Speicherplatz ( den er benutzen darf ).

    *f[i][j]=*src.f[i][j];
    

    Wir reden hier vom operator= und nicht dem CopyCtor. Warum sollten die Pointer nicht auf einen Speicherplatz zeigen?

    Falls du jetzt meinst, dass einige auf NULL zeigen, dann hast du genau das wiederholt, was ich in meinem vorherigen Post geschrieben habe.

    Das Topic ging ja ursprünglich in der Tat um den CopyCtor, und der sah/sieht genau so aus. Dein Code für den op= ist fast wie er sein sollte (lieber *this zurück als Referenz zurückgeben), aber falsch für den CopyCtor.

    Also wo kommen die Foo Objekte her? Und setzt du die gesamte Matrix auf 0 in deinen Konstruktoren, oder Default-Foos oder sowas?



  • Ich setze die gesamte Matrix im Ctor auf NULL.
    Mittels eines setters

    setElement(int x,int y, Foo* f)
    

    setze ich dann die jeweiligen Elemente.
    Die Foos, die ich als Parameter benutze, kommen aus main(), wo ich sie statisch auf dem stack definiert habe.



  • Raptor schrieb:

    Ich setze die gesamte Matrix im Ctor auf NULL.
    Mittels eines setters

    setElement(int x,int y, Foo* f)
    

    setze ich dann die jeweiligen Elemente.
    Die Foos, die ich als Parameter benutze, kommen aus main(), wo ich sie statisch auf dem stack definiert habe.

    Ok.

    mal angenommen du hast ein einen Pointer p der zeigt auf 0 ( das ist dein Array in der klasse )
    und nun kommt ein pointer o der auf 4 Byte zeigt an der adresse 0x24234FFA ( Das sind deine daten aus Main )

    und DU machst dann *p (ups du dereferenzierst NULL ? ) = *o;

    Verstanden? Du hast keinen Speicherplatz für deine Daten!!!



  • Okay - Es gilt Speicherplatz zu beschaffen.
    Was schlagt ihr vor?



  • Raptor schrieb:

    Ich setze die gesamte Matrix im Ctor auf NULL.
    Mittels eines setters

    setElement(int x,int y, Foo* f)
    

    setze ich dann die jeweiligen Elemente.
    Die Foos, die ich als Parameter benutze, kommen aus main(), wo ich sie statisch auf dem stack definiert habe.

    Auf dem Stack? Dann könnte die Lösung knifflig werden. Du musst nämlich nicht nur bei src, sondern auch bei *this auf != 0 achten.

    Mit jeweils einmaligen Foos auf dem Heap könnte die Lösung ungefähr so aussehen:

    inline bool Bar::hasElement( std::size_t row, std::size_t col ) const
    {
      return matrix_[row][col] != 0;
    }
    
    void Bar::setElement( std::size_t row, std::size_t col, Foo* f )
    {
      if (f != 0) {
        if (hasElement(row, col)) {
          *matrix_[row][col] = *f;
        } else {
          matrix_[row][col] = new Foo(*f);
        }
      } else if (hasElement(row, col)) {
        delete matrix_[row][col];
        matrix_[row][col] = 0;
      }
    }
    
    Bar& Bar::operator=( Bar const& src )
    {
      for (int row = 0; row < 10; ++row) {
        for (int col = 0; col < 10; ++col) {
          setElement(row, col, src.matrix_[row][col]);
        }
      }
      return *this;
    }
    

    Könnte ungefähr sein was du suchst, aber auch komplett daneben.
    Schwer zu sagen ohne zu wissen was Foo & Bar eigentlich sind, wieso unbedingt Pointer und nicht schlicht Objekte wenn du jene ohnehin immer kopierst/zuweist, es offensichtlich nicht wirklich "Referenzen" sind...



  • Ok.
    Ich sehe schon.
    Ich werde wohl auf den Heap ausweichen.
    Ist denke ich die bessere Loesung.



  • Ich hab noch mal ueber den fehlenden Speicher gegruebelt.
    Ich kann ja auch folgendes machen, ohne extra Speicher anzufordern:

    int main()
    {
        char* arr = "abcdefghijklm";
    
        return 0;
    }
    

    Ich glaube euch ja, dass ich keinen Speicher habe, aber warum?
    Warum muss ich bei meinem Problem extra welchen anfordern?
    Die Array-Groessen sind doch bekannt.



  • Raptor schrieb:

    Ich glaube euch ja, dass ich keinen Speicher habe, aber warum?
    Warum muss ich bei meinem Problem extra welchen anfordern?
    Die Array-Groessen sind doch bekannt.

    Es sind nicht die Pointer in deiner Matrix denen Speicher fehlt. Es sind die Objekte auf die sie zeigen sollen.



  • Es sind nicht die Pointer in deiner Matrix denen Speicher fehlt. Es sind die Objekte auf die sie zeigen sollen.

    huh?

    evilissimo schrieb:

    Verstanden? Du hast keinen Speicherplatz für deine Daten!!!



  • Raptor schrieb:

    Es sind nicht die Pointer in deiner Matrix denen Speicher fehlt. Es sind die Objekte auf die sie zeigen sollen.

    huh?

    evilissimo schrieb:

    Verstanden? Du hast keinen Speicherplatz für deine Daten!!!

    Wird das ein ASW-Experiment?



  • 😞
    Also. Ich hatte gedacht, wenn ich mein Array mittels der Schleifen durchlaufe...

    for(int i=0; i<10; ++i)
            for(int j=0; j<10; ++j)
                if(src.f[i][j] != NULL)
                    *f[i][j]=*src.f[i][j]; //...dann wird hier doch der inhalt von
                                           // *src.f[i][j] kopiert - damit waeren doch 
                                           // schonmal Objekte vorhanden
    

    Warum meinst du trotzdem, die Objekte wuerden fehlen?



  • Spiel einfach mal folgendes Beispiel durch:

    { { x, x, x },            { { y, y, y },
      { 0, x, x },      =       { y, y, 0 },
      { 0, 0, x } }             { y, 0, 0 } }
    


  • Leider kann ich erst jetzt wieder antworten und muss das hier wieder aufwaermen.
    (2Wochen Umbau, daher kein PC, dann 2 Wochen Urlaub wieder kein PC.)
    Hab dein Beispiel mal getestet

    int main()
    {
        //dass es mit NULL net funktioniert weiss ich ja schon
        /*int arr00[][3] = { { 1, 1, 1 },
                           { NULL, 1, 1 },
                           { NULL, NULL, 1 } };
    
        int arr11[][3] = { { 2, 2, 2 },
                           { 2, 2, NULL },
                           { 2, NULL, NULL } };*/
    
        int arr0[][3] = { { 1, 1, 1 },
                          { 42, 1, 1 },
                          { 42, 42, 1} };
    
        int arr1[][3] = { { 2, 2, 2 },
                          { 2, 2, 42 },
                          { 2, 42, 42 } };
    
        for(int i=0; i<3; ++i)
            for(int j=0; j<3; ++j)
                arr0[i][j]=arr1[i][j];     
    
        return 0;
    }
    

    Funktioniert soweit wunderbar.


Anmelden zum Antworten