problem ze zwalnianiem pamięci delete

problem ze zwalnianiem pamięci delete
S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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.

Kopiuj
#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;
}

superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Kraków
  • Postów:1999
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.


S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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

Kopiuj

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

superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Kraków
  • Postów:1999
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.


S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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.

Delor
Przeczytaj jeszcze raz pierwszą odpowiedź. (skasuj int * w linii 19)
S7
Ok teraz dopiero skumalem wielkie dzieki wszystko dziala
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Kraków
  • Postów:1999
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

Kopiuj
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.


edytowany 1x, ostatnio: cerrato
S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
0

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

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
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:

Kopiuj
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.

S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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

superdurszlak
@Mr.YaHooo napisał Ci prawdę, a Ty odpowiadasz aroganckimi odzywkami. Widzisz, ale nie czytasz ze zrozumieniem tych komunikatów.
S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
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.

S7
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:62
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.

edytowany 1x, ostatnio: srk71
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:3 dni
  • Lokalizacja:Szczecin
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.


Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)