delete von dyn. Array



  • mit c++ bin ich noch ein ziemlicher anfänger.

    wie lösche ich ein dyn. erstelles array?

    beispiel:

    int** population;
    population = new int*[5];
    for(int i = 0; i < 5; i++){
      population[i] = new int[7];
    }
    
    for(int i = 0; i < 5; i++){
      delete[] population[i];
    }
    delete[] population;
    

    Habe schon einige andere Varianten ausprobiert, die mir so eingefallen sind. aber immer meckert valgrind.
    hier bekomme ich:
    Invalid read of size 4
    und
    Invalid free() / delete / delete[] / realloc()

    wäre super, wenn mir jemand helfen könnte



  • Nutz std::vector.



  • Weil es so nicht geht oder weil std::vector einfacher bzw. besser ist?

    Geht es denn so wie ich es vor habe??



  • Mh eigentlich sieht das so schon richtig aus, solange die Arraygrenzen stimmen, natürlich nur.

    Dass es nicht intelligent ist, wurde ja schon gesagt...



  • AnfängerNr1 schrieb:

    Weil es so nicht geht

    Rein theoretisch geht es natürlich so.

    ...oder weil std::vector einfacher bzw. besser ist?

    Ja. Der kümmert sich von alleine um den Speicher und su..

    Geht es denn so wie ich es vor habe??

    Ja, es geht so.
    Allerdings ist es sehr umständlich das richtig - im Sinne von exception safety - manuell hinzukriegen. Manuelle Speicherverwaltung ist in modernem C++ "nie" mehr notwendig, denn C++ hat Destruktoren. Dieses sog. RAII-Idiom ist extrem mächtig und vereinfacht Code.
    Um aufzuzeigen, was an deinem Codebeispiel falsch ist (neben dem Valgrind Fehler wo ich keine Ahnung habe, wo der herkommt):
    Nehmen wir mal an es wird Speicher für 5 int-Pointer angefordert. Anschließend beginnt die Schleife. Im dritten Durchgang schlägt die Allokation jedoch fehl. Es wird eine Exception geworfen und zum letzten try-Block zurückgerollt. Wer gibt jetzt den bereits angeforderten Speicher für die 5 int-Pointer und die zwei 7-int-Arrays frei? Nur das OS nach Programmterminierung. In vielen Anwendungen ist das nicht gut.
    Kapselt man das in eine Klasse mit Destruktoren, hat man das Problem nicht. Denn beim zurückrollen zum letzten try-Block kümmert sich die Runtime um das Aufrufen der Destruktoren, die bereits angeforderten Speicher freigeben. Problem gelöst.
    Und std::vector macht genau das*.

    *Zwar eindimensional, aber mehrdimensionale Arrays sollte man eh durch Indexkalkulationen auf eindimensionale abbilden, damit der Speicher am Stück ist.



  • Hey Nathan,

    danke für die Antwort. Würde das gerne mal mit Vector ausprobieren.
    Aber am besten natürlich dann direkt mit der Indexkalkulationen.
    Könntest du mir dafür ein kleines Beispiel geben.

    Danke



  • Wie man einen vector nutzt, weißt du?
    Ansonsten das mit dem Index ist eig. ganz simpel.
    Nehmen wir mal an du hast folgende Matrix:

    1 2 3
    4 5 6
    7 8 9
    

    Das Element 1 liegt zweidimensional an Position [0][0], das Element 5 an [1][1] und 9 an [2][2]. Soweit noch alles klar.
    Aber nehmen wir mal an, dass läge eindimensional im Speicher, d.h. alle Elemente in einer Reihe. Es gibt nun zwei Möglichkeiten das anzuordnen.

    1 2 3 4 5 6 7 8 9
    

    und

    1 4 7 2 5 8 3 6 9
    

    In der ersten Version bin ich Zeile für Zeile durchgegangen und habe eine Zeile nach der anderen gespeichert in der zweiten Spalte für Spalte. Anhand der Nummern siehst du vielleicht schon, dass ich die erste Methode verwenden werde. Das nennt man dann auch row-major order.
    Das erste Element der ersten Zeile liegt nun einfach an Position [0]. Das zweite Element der ersten Zeile an Position [1] und das dritte an Position [2]. Wo liegt nun das erste Element der zweiten Zeile? An Position [3]. Wo liegt das i-te Element der zweiten Zeile? An Position [3 + i]. Und das i-te Element der zweiten? An Position [6 + i].
    Es lässt sich ein Muster erkennen. Die Zahl davor ist immer die Anzahl der Elemente einer Zeile multipliziert mit dem Index des Elementes. Und das ist auch schon die komplette Indexkalkulation. Das i-te Element der j-ten Zeile liegt an Position [j * 3 + i]. Oder für allgemeinere Arrays [j * ElementeProZeile + i].
    Falls du das nicht verstehst, rechne das ruhig mal für verschiedene Werte und Größen aus.

    Ein kleiner Nachtrag noch: Wenn du "rohe" multidemnsionale Arrays benutzt (int arr[3][3]) macht der Compiler genau die selben Rechnungen und zwar auch wie ich row-major.



  • cool, danke.
    das ist ziemlich verständlich und sieht auch nicht kompliziert aus.
    wird direkt mal ausprobiert...



  • für den Fall dass du mal tatsächlich ein dynamisches Array im C Stil verwenden willst, nütze die Vorteile von C++.
    Stichwort: RAII (kurz gesagt: das Ding löscht sich selber)

    boost bietet da praktische Klassen, z.B.: boost::shared_array

    Ansonsten: Nimm std::vector.



  • Du löscht nicht selbst sondern verwendest unique_ptr. vector ist je nach Einsatzzweck einfach nur unnötig.

    #include <memory>
    
    int main()
    {
    	using namespace std;
    
    	unique_ptr<unique_ptr<int[]>[]> population(new unique_ptr<int[]>[5]);
    	for(int i = 0; i < 5; ++i)
            population[i].reset(new int[7]);
    }
    


  • Ethon schrieb:

    Du löscht nicht selbst sondern verwendest unique_ptr. vector ist je nach Einsatzzweck einfach nur unnötig.

    #include <memory>
    
    int main()
    {
    	using namespace std;
    
    	unique_ptr<unique_ptr<int[]>[]> population(new unique_ptr<int[]>[5]);
    	for(int i = 0; i < 5; ++i)
            population[i].reset(new int[7]);
    }
    

    Ich glaube, was perverseres hab ich noch nie gesehen.



  • Kellerautomat schrieb:

    Ethon schrieb:

    Du löscht nicht selbst sondern verwendest unique_ptr. vector ist je nach Einsatzzweck einfach nur unnötig.

    #include <memory>
    
    int main()
    {
    	using namespace std;
    
    	unique_ptr<unique_ptr<int[]>[]> population(new unique_ptr<int[]>[5]);
    	for(int i = 0; i < 5; ++i)
            population[i].reset(new int[7]);
    }
    

    Ich glaube, was perverseres hab ich noch nie gesehen.

    Dann hast du hier etwas Perverseres:

    #include <vector>
    
    int main()
    {
    	using namespace std;
    
    	vector<vector<int>> population(5);
    	for(int i = 0; i < 5; ++i)
                population[i].resize(7);
    }
    

    Edit: Okay, die Schleife kann beim vector weg:

    #include <vector>
    
    int main()
    {
    	using namespace std;
    
    	vector<vector<int>> population(5, vector<int>(7));
    }
    

    Trotzdem ist vector nicht für Arrays mit fixer größe da.



  • Beides gleich scheisse. Da der TE offensichtlich ein 2D Array will, waere Indizes umrechnen in einem vector/unique_ptr<T[]> besser. Welches davon kommt auf den Anwendungsfall an.



  • Ethon schrieb:

    Trotzdem ist vector nicht für Arrays mit fixer größe da.

    Stimmt, dafür gibt es std::array...



  • Kellerautomat schrieb:

    Beides gleich scheisse. Da der TE offensichtlich ein 2D Array will, waere Indizes umrechnen in einem vector/unique_ptr<T[]> besser. Welches davon kommt auf den Anwendungsfall an.

    Überlest ihr alle meine Beiträge oder was?



  • Nathan schrieb:

    Kellerautomat schrieb:

    Beides gleich scheisse. Da der TE offensichtlich ein 2D Array will, waere Indizes umrechnen in einem vector/unique_ptr<T[]> besser. Welches davon kommt auf den Anwendungsfall an.

    Überlest ihr alle meine Beiträge oder was?

    noch nicht genug aufmerksamkeit was 🙄



  • adhs schrieb:

    Nathan schrieb:

    Kellerautomat schrieb:

    Beides gleich scheisse. Da der TE offensichtlich ein 2D Array will, waere Indizes umrechnen in einem vector/unique_ptr<T[]> besser. Welches davon kommt auf den Anwendungsfall an.

    Überlest ihr alle meine Beiträge oder was?

    noch nicht genug aufmerksamkeit was 🙄

    Ich mein ja nur: Die sagen genau das, was ich auch schon gesagt hatte...


  • Mod

    Nathan schrieb:

    Ich mein ja nur: Die sagen genau das, was ich auch schon gesagt hatte...

    Reagiere doch nicht auf solche Trolle.

    asc schrieb:

    Stimmt, dafür gibt es std::array...

    Wie jetzt? So?

    std::vector<std::array<int, 4000>> vec(10000);
    


  • Hallo, ich bins nochmal.
    Gibt es für diese Indexkalkulation einen Fachbegriff, den man in der Literatur findet? Bei Indexkalkulation ist es ein bisschen mau...
    Darf auch gerne ein englischer Begriff sein.
    Danke



  • Indexierung, Indizierung, Indexoperator - in der Richtung würd ich mal suchen.

    Was brauchst du denn? Bzw was willst wissen?


Log in to reply