Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

c++ dynamiczna alokacja pamięci _ funkcja delete.

Tojmak987123 04 Paź 2017 21:57 651 12
  • #1 04 Paź 2017 21:57
    Tojmak987123
    Poziom 3  

    Witam,

    zastanawiam się dlaczego poniższy kod wyrzuca błąd? Wiem, że dotyczy on jednej z ostatnich linijek kodu -> delete[] tablica;. Czy mógł bym prosić o wytłumaczenie?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 12
  • #2 04 Paź 2017 22:22
    Stefan_2000
    Poziom 18  

    Zgaduję, że to dlatego, że w momencie gdy wołasz:
    delete[] tablica;
    to zmienna tablica nie pokazuje już na oryginalny początek tablicy.

    Zamiast ,,bawić się'' w przesuwanie wskaźnika tablica tam i z powrotem, lepiej by było zapamiętać oryginalny wskaźnik, a do wpisywania wartości użyć jego kopii.

    0
  • Pomocny post
    #3 04 Paź 2017 22:45
    hello_world
    Poziom 10  

    Ponieważ

    Kod: c
    Zaloguj się, aby zobaczyć kod
    to wskaźnik na tablicę, czyli wskaźnik, więc używamy
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kod: c
    Zaloguj się, aby zobaczyć kod
    użyjemy w przypadku użycia wskaźnika na tablicę wskaźników, czyli wskaźnik na wskaźnik
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #4 05 Paź 2017 00:02
    Stefan_2000
    Poziom 18  

    Oczywiście hello_world ma więcej racji ode mnie.
    Niemniej przechowywanie oryginalnego wskaźnika na początek tablicy jest dobrym pomysłem.

    0
  • Pomocny post
    #5 05 Paź 2017 10:07
    hello_world
    Poziom 10  

    Co do powyższego to owszem, wskaźnik to po prostu komórka pamięci przechowująca adres do innej komórki, gdy dokonamy inkrementacji (++) lub dekrementacji (--) zmienimy zawartość wskaźnika, adres wskaźnika jest nadal ten sam.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #6 05 Paź 2017 10:39
    Tojmak987123
    Poziom 3  

    Stefan_2000, czyli proponujesz rozwiązanie tego typu?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dziękuje obu Panom za pomoc.

    Dodano po 11 [minuty]:

    hello_world, tą idee wydaje mi się, że rozumiałem. Nie wiedziałem, że funkcja delete wymaga"przestawienie" wskaźnika z powrotem na początek tego co wskazywał? Bo teoretycznie po spróbowaniu faktycznie okazuje się, że program nie wywala się w momencie, w którym ustawie wskaźnik z powrotem na początkowe miejsce. Czyli np biorąc pod uwagę początkowo wysłany przeze mnie kod, po dodaniu linijki : tablica -= ile; (przed wykasowaniem tablicy). Czyli wtedy wskaźnik tablica znowu wskazuje pamięć, do której odnosił się początkowo. Mogę to interpretować w ten sposób, że funkcja delete czyści pamięć wskazywanej tablicy przechodząc do kolejnych jej "szufladek"? Czyli czyści najpierw szufladkę [0], później [1] .... [n]. Błąd był dlatego, że nie czyściłem całkowicie utworzonej tablicy?

    0
  • #7 05 Paź 2017 11:10
    hello_world
    Poziom 10  

    delete nie jest funkcją tylko operatorem zwalniania pamięci przydzielonej dynamicznie.

    Nie musisz wracać wskaźnika na początek, bo na wstępie kompilator ma pokazane na co wskazuje wskaźnik i delete zeruje wszystko co wskazywał.

    0
  • #8 05 Paź 2017 11:35
    Tojmak987123
    Poziom 3  

    To dlaczego powrót wskaźnikiem na początek usunął błąd?

    0
  • #9 05 Paź 2017 11:42
    hello_world
    Poziom 10  

    Zależy od kompilatora, u mnie wszystko działa

    0
  • Pomocny post
    #10 05 Paź 2017 13:53
    rajszym
    Poziom 19  

    hello_world napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    użyjemy w przypadku użycia wskaźnika na tablicę wskaźników, czyli wskaźnik na wskaźnik
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nieprawda, ten kod nie ma prawa działać, choć przez pewien czas będzie.
    W uproszczeniu delete[] służy do dealokacji tablic klas.
    hello_world napisał:
    Nie musisz wracać wskaźnika na początek, bo na wstępie kompilator ma pokazane na co wskazuje wskaźnik i delete zeruje wszystko co wskazywał.

    To również nieprawda.
    Cytat:

    1) Called by delete-expressions to deallocate storage previously allocated for a single object. The behavior of the standard library implementation of this function is undefined unless ptr is a null pointer or is a pointer previously obtained from the standard library implementation of operator new(size_t) or operator new(size_t, std::nothrow_t).
    2) Called by delete[]-expressions to deallocate storage previously allocated for an array of objects. The behavior of the standard library implementation of this function is undefined unless ptr is a null pointer or is a pointer previously obtained from the standard library implementation of operator new[](size_t) or operator new[](size_t, std::nothrow_t).

    1
  • #11 05 Paź 2017 22:36
    hello_world
    Poziom 10  

    Oczywiście, przyznaję swój błąd. Sprawdziłem to co napisałeś w debugerze i owszem są komórki pamięci nietknięte przez operator delete. Człowiek uczy się całe życie...

    0
  • Pomocny post
    #12 05 Paź 2017 23:19
    krru
    Poziom 32  

    Stefan_2000 napisał:
    Oczywiście hello_world ma więcej racji ode mnie.
    Niemniej przechowywanie oryginalnego wskaźnika na początek tablicy jest dobrym pomysłem.


    Nie ma w ogóle racji. Jeśli new było z [] to delete też powinno być z [].

    Twoja diagnoza jest słuszna - po wcześniejszych pętlach w kodzie było przywrócenie oryginalnej wartości wskaźnika przez odjęcie:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    ale brakuje tego po ostatniej pętli a przed delete.

    0
  • #13 06 Paź 2017 15:23
    Tojmak987123
    Poziom 3  

    Temat wydaje mi się już jasny, dziękuje wszystkim bardzo za szybkie i trafne rady :).

    0