problem ze zwalnianiem pamięci delete

0

Czy jest w stanie mi ktoś wytłumaczyć dlaczego poniższy kod się nie kompiluje? Błąd w linii 19 - próba ponownego zadeklarowania wcześniej zadeklarowanej tablicy dynamicznej, ale w 16 linii ją zwalniam, więc nie wiem o co chodzi.

#include <iostream>

using namespace std;

int main()
{
    int tablica1[5]={1,2,3,4,5};
    int * wskaznik = new int[5];

    for (int i=0;i<5;i++)
        {
        wskaznik[i]=tablica1[i];
        cout<<wskaznik[i]<<endl;
        }

        delete [] wskaznik;

        int tablica2[2]={7,8};
        int * wskaznik = new int[2];
        for (int i=0;i<2;i++)
        {
        wskaznik[i]=tablica2[i];
        cout<<wskaznik[i]<<endl;
        }
        for (int i=0;i<5;i++)
        {
        cout<<wskaznik[i]<<endl;
        }

    return 0;
}

0

Operator delete ma zwolnić pamięć zajmowaną przez obiekt (w Twoim przypadku tablicę) który istniał w pamięci i na który wskazywał Twój wskaźnik, a nie "zlikwidować" czy "wyrzucić" deklarację tego wskaźnika ze scope'a i umożliwić ponowną deklarację.

W linii 19 zamiast deklaracji użyj przypisania i tyle.

0

delete powinien zwolnić pamięć a jej nie zwalnia, pamiętam jak robiłem zadania z Prata to po delete i probie wywolania tej samej tablicy pokazywaly sie smieci a u nie wciaz te same wartosci, nie moge sie dogrzebac do tego w ksiazce. Wklejam kolejny kod ktory moze wyjasni o co mi chodzi


using namespace std;

int main()
{
    int tablica1[5]={1,2,3,4,5};
    int * wskaznik = new int[5];

    for (int i=0;i<5;i++)
        {
        wskaznik[i]=tablica1[i];
        cout<<wskaznik[i]<<endl;
        }

        delete [] wskaznik;


        for (int i=0;i<5;i++)
        {
        cout<<wskaznik[i]<<endl;
        }

    return 0;
}

zamiast pokazywac smieci po delete wskaznik dalej pokazuje przypisane wartosci

0

Zwolnienie pamięci nie oznacza, że w zwolnionym obszarze pamięci automatycznie pojawią się jak to opisałeś "śmieci". Zwolnienie pamięci oznacza, że może ona zostać ponownie zaalokowana i wykorzystana do innych potrzeb - skutkiem tego jest pojawianie się "śmieci". Wskaźnik dalej będzie na ten obszar wskazywał i przez jakiś czas pewnie dalej będą tam istnieć stare wartości, ale po jakimś czasie mogą zostać nadpisane przez coś innego.

0

Ok, rozumiem. W takim razie jak mogę użyć tego samego wskaźnika kiedy potrzebuje zapisać w nim mniejszą tablicę, skoro "new" zadeklarowało w moim przypadku ze potrzebuje dynamiczna tablice na 5 elementow, ale potem chce tam wsadzic tylko 2 a potem moze 7. Potrzebne mi to bo pisze "akinatora" i potrzebuje zmniejszajaca sie dynamiczna tablice struktur z której w kolejnych pętlach beda usuwane kolejne niepasujace elemnty (zmniejszajacy sie zbior danych) , tak aby wczesniej usuniete elementy nie byly brane pod uwage w kolejnej petli.

1

Jeśli bardzo Ci zależy na ponownym użyciu tego samego wskaźnika na zupełnie nową tablicę, to alokujesz od nowa i tyle

int * some_array = new int[4];
// coś robisz
delete [] some_array;
some_array = new int[1000];
// znowu coś robisz
delete [] some_array;
// i tak dalej

Ale generalnie mam wrażenie, że w przypadku gdy rozmiar Twoich danych ma się cały czas zmieniać to tablica może nie być najszczęśliwszym wyborem, jeśli chodzi o strukturę do ich przechowywania.

Rozumiem, że docelowo będziesz potrzebował czasem usunąć jakiś element, czasem dodać nowe, więc rozmiar będzie się zmieniał w trakcie - jeśli nie masz narzuconego wykorzystania tablic to może poczytaj np. o listach i innych strukturach, oszczędzisz sobie tego alokowania, zwalniania, przenoszenia, realokowania itd.

0

robie po kolei rzeczy z ksiazki Prata o listach tam chyba nic nie ma, dzieki za pomoc

3

Moja mała rada. Widzę, że próbujesz ogarnąć dynamiczne przydzielanie pamięci, a nie umiesz jeszcze podstawowych podstaw. Nie czytasz również komunikatów kompilatora. Ładnie Ci mówi, co jest nie tak z Twoim kodem źródłowym:

main.cpp: In function ‘int main()’:
main.cpp:19:15: error: redeclaration of ‘int* wskaznik’
         int * wskaznik = new int[2];
               ^~~~~~~~
main.cpp:8:11: note: ‘int* wskaznik’ previously declared here
     int * wskaznik = new int[5];
           ^~~~~~~~

Jasno wynika z tego, ze masz redeklarację zmiennej wskaznik Generalnie poczytaj o zasięgu zmiennych, bo to są naprawdę podstawy. Jeśli tego nie ogarniesz będzie Ci ciężko i szybko się zniechęcisz. Nie mówię tego po złości, ale taka prawda. Przystopuj i naucz się podstaw.

0

jasno napisałem w pierwszym poscie, ze widze co mowi kompilator, po prostu nie wiedzialem ze raz zadeklarowanej tablicy dynamicznej nie wywoluje sie ponownie do pracy przez ponowne jej zadeklarowanie a jedynie przypisanie. Mala rada bo widze, ze lubisz blyszczec. Jak nie masz nic wartosciowego do powiedzenia do porpstu nie pisz

0

Ok, moze sie rzeczywiscie unioslem, ale odebralem to nie jako chec pomocy, a zwykla zlosliwosc. Jezeli poswiecil swoj prywatny czas, zeby dac mi swietna rade "wracaj do szkoly" to jakos przecierpie, jesli nastepnym razem nie kiwnie palcem. W kazdym razie przepraszam, bo to rzeczywiscie nieeleganckie bylo. Dziekuje tym, ktorzy pomogli i przepraszam @mr.YaHooo, milej soboty.

0
srk71 napisał(a):

jasno napisałem w pierwszym poscie, ze widze co mowi kompilator, po prostu nie wiedzialem ze raz zadeklarowanej tablicy dynamicznej nie wywoluje sie ponownie

Hmm możesz rozwinąć co masz na myśli o wywoływaniu ponownie tablicy? Bo komunikat kompilatora redeclaration of ‘int* wskaznik’ tyczy się po prostu zadeklarowanej dwa razy zmiennej o takiej samej nazwie. Nie ma tu nic mowy o żadnej tablicy dynamicznej. Analogicznie jakbyś dwa razy próbował zadeklarować zmienną o nazwie a będącej zwykłym int

Co do mojej wypowiedzi, to nie była w złym tonie. Po prostu zwróciłem uwagę, że masz problemy z podstawami. Deklaracja zmiennych oraz ich zasięgi są o wiele wcześniej niż dynamiczne zarządzanie pamięcią. Można to porównać do nauki alfabetu. Nie nauczysz się płynnie czytać jeśli nie będziesz znał wszystkich liter bardzo dobrze.

0

Myslalem, ze delete odsyla tablice dynamiczna w "niebyt" i nalezy ja ponownie zadeklarowac (zwlaszcza ze bedzie miala inna wielkosc) i dlatego nie rozumialem dlaczego wyskakuje informacja o bledzie proby ponownej deklaracji, myslalem ze cos nie tak z instrukcja zwolnienia pamieci. W ksiazkach i przykladach uzycia tablic dynamicznych z netu nie doszukalem sie przykladu kodu ktory wielokrotnie zwalnial i zapelnial tablice (raczej raz new i raz delete) i postanowilem zapytac na forum. Zasiegi zmiennych to banalny temat i dlatego sie zirytowalem, ale rzeczywiscie o to wlasnie chodzi.

0

Tak na marginesie: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Dobra rada: zmień ksiażkę na jakąś lepszą. Prata ma słabe recenzje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1