dynamisches Array löschen, das von einer Funktion erstellt wurde



  • Hallo!

    Ich habe eine Funktion, sagen wir

    void getarray(pdata[],int*size){
       pdata=new long[100]; //natürlich nicht immer 100
    }
    

    und die rufe ich jetzt auf

    long*pdata;
    int size;
    
    getarray(pdata,&size);
    

    und jetzt meine Frage:

    Wie kann ich den Speicher später wieder freigeben? Im Netz habe ich nur delete und delete [] für Arrays gefunden. Beides geht aber nicht, da der delete-Befehl die Größe des Arrays ja nicht kennt.

    delete [size] pdata //das wär cool :)
    

    MfG,
    Mircode



  • Bei delete[] musst (und kannst) du nicht selbst die Größe angeben, die wird intern festgehalten. delete will nur einen Zeiger auf den Speicherbereich, dann klappt das Freigeben auch.

    Abgesehen davon ist Reservieren und Freigeben von Speicher auf unterschiedlichen Ebenen imho sehr unschön und verleitet zu Fehlern. Du könntest eine ...Alloc und eine ...Free-Funktion schreiben, oder gleich eine Klasse, die sich (z.B. im Destruktor) um das Aufräumen kümmert.



  • Oder verwende gleich std::vector.



  • So wie die Funktion da steht funktioniert die sowieso nicht da der Arrayzeiger in die Funktion kopiert wird. Du siehst die Änderung außerhalb der Funktion also nicht.
    Entweder du übergibst den Zeiger als Referenz oder (besser) du lässt die Funktion den Zeiger einfach zurückgeben.
    Ich stimme _matze auch zu. Sowas ist sehr unschön. Warum brauchst du das so?



  • Danke für die schnelle Antwort!

    Bei delete[] musst (und kannst) du nicht selbst die Größe angeben, die wird intern festgehalten. delete will nur einen Zeiger auf den Speicherbereich, dann klappt das Freigeben auch.

    Naja, ich kann delete[] pdata; aufrufen, dann stürzt aber alles ab. Ist auch verständlich.

    Mein Array hat auch eine akzeptable maximale Größe, ich kann es zur Not auch statisch machen. Aber ich will ja was dazulernen 🙂

    Abgesehen davon ist Reservieren und Freigeben von Speicher auf unterschiedlichen Ebenen imho sehr unschön und verleitet zu Fehlern.

    Man muss auch mal was riskieren im Leben.

    Du könntest eine ...Alloc und eine ...Free-Funktion schreiben, oder gleich eine Klasse, die sich (z.B. im Destruktor) um das Aufräumen kümmert.

    Und wie mache ich das? Innerhalb der Free-Funktion bzw. im Destruktor weiß ich doch auch nur indirekt die Größe des Arrays, z.B. weil ich sie in einer Variable mitgebe...



  • Oh Mann ich komm garnicht hinterher so wie es hier Antworten hagelt...

    So wie die Funktion da steht funktioniert die sowieso nicht da der Arrayzeiger in die Funktion kopiert wird.

    War ich wieder zu eilig.

    void getarray(long *pdata[],int*size){
       pdata=new long[100]; //natürlich nicht immer 100
       size=100;
    }
    
    long*pdata;
    int size;
    
    getarray(&pdata,&size);
    

    Ich hoffe, dass jetzt alles stimmt.

    Ich stimme _matze auch zu. Sowas ist sehr unschön. Warum brauchst du das so?

    Es kann doch oft vorkommen, dass ich eine Funktion haben will, die z.B. ein Bild oder eine Zeichenkette zurückgibt, von der ich die Größe nicht vorher kenne. Wie mache ich das denn schön?

    Mir fällt noch ein:

    size=getArraySize(bla);
    pdata=new long[size];
    getArray(pdata);
    ...
    delete [] pdata;
    

    Aber dann brauche ich 2 Extra-Funktionen...



  • Mircode schrieb:

    Bei delete[] musst (und kannst) du nicht selbst die Größe angeben, die wird intern festgehalten. delete will nur einen Zeiger auf den Speicherbereich, dann klappt das Freigeben auch.

    Naja, ich kann delete[] pdata; aufrufen, dann stürzt aber alles ab. Ist auch verständlich.

    Braunstein hat es schon erklärt. Du übergibst deine Zeiger-Variable, an die Funktion, dies aber by-value! Das heißt, dass die lokale Zeigervariable zwar auf den gleichen Bereich zeigt, wie ihr Ursprung, aber selbst nicht die gleiche Adresse hat. Dementsprechend kannst du mit so einem Konstrukt zwar immer das ändern, worauf der Zeiger zeigt, aber wenn du die Zeigervariable selbst ändern willst, musst du sie per Zeiger auf Zeiger ("**") oder Referenz ("&") übergeben.



  • Programmiere C++

    class Image {
       std::vector<int> bits;
    // usw
    };
    
    Image load() {
       Image img;
       // Daten laden
       return img;
    }
    

    Für Zeichenketten gibt es doch std::string.
    Rohe Arrays rumreichen wirst du C++ extrem selten, du solltest das in Klasssen kapseln.

    // edit:
    Und wer beim Programmieren etwas riskieren will, sollte auf den Mondgeschossen werden 😛
    Wenn eine Herangehensweise Probleme bereiten kann suche ich nach einer besseren Lösung.



  • Man könnte auch über Smartpointer nachdenken falls ein vector nicht in Frage kommt (aus welchen Gründen auch immer).



  • Smartpointer würd ich jetzt erstmal nicht empfehlen, solange nicht klar ist, was er machen möchte.

    Es kann doch oft vorkommen, dass ich eine Funktion haben will, die z.B. ein Bild oder eine Zeichenkette zurückgibt, von der ich die Größe nicht vorher kenne.

    Das ist prozedural gedacht. In C++ wirst Du üblicherweise ein Bild in einer Klasse kapseln, sprich: Nein, so etwas sollte eigentlich nicht vorkommen. 😉

    Angenommen, Du nutzt irgendeine Grafikbibliothek, um Bilder zu laden. Sehr häufig wird dir das natürlich nur Rohdaten, d.h. einen Zeiger auf Speicher zurückliefern. Dann wirst Du diesen Speicher aber eben in einer Klasse kapseln und gut ist.

    Ich empfehle Dir ein Buch. C++ Primer oder so, das wird hier immer gern empfohlen.


Anmelden zum Antworten