• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Tajemnicza struktura i delete

Object Storage Arubacloud
–1 głos
225 wizyt
pytanie zadane 13 lipca 2016 w C i C++ przez SebekMakaron Obywatel (1,290 p.)

Witam. Na wstępie napiszę że naturalne i konieczne jest usuwanie zaalokowanej dynamicznie pamięci ze zmiennych:

int *zmienna = new int;
delete zmienna;

Lecz przechodząc do konkretnego pytania czy należy usuwać zaalokowaną pamięć w strukturach:

WrogiStatek* NowyStatek()
{
     WrogiStatek* w_statek = new WrogiStatek;
....
....
     return w_statek;
}

Niestety nie zauważyłem aby autor zaprzeczył lub potwierdził ten fakt, dlatego zwracam się do was z prośba o odpowiedz na to pytanie.

3 odpowiedzi

0 głosów
odpowiedź 13 lipca 2016 przez SebekMakaron Obywatel (1,290 p.)
wybrane 14 lipca 2016 przez SebekMakaron
 
Najlepsza

Proszę o wskazówkę do kodu poniżej:

#include <cstddef>
#include <iostream>

using namespace std;

struct WrogiStatek
{
     int index;
     int bron;
     WrogiStatek* w_n_statek;
};

WrogiStatek* NowyStatek(WrogiStatek* w_lista)
{
     WrogiStatek* w_statek = new WrogiStatek;
     w_statek->index =0;
     w_statek->bron =10;
     w_statek->w_n_statek = w_lista;
     return w_statek;
}

void Usun(WrogiStatek* w_lista, int ilosc);

int main()
{
     WrogiStatek* w_lista = NULL;
     int ilosc;
     cout<<"Ile statkow chcesz stworzyc?: ";
     cin>>ilosc;

     for(int i=0; i<ilosc; i++)
     {
          w_lista = NowyStatek(w_lista);
          w_lista->index = i+1;
          cout<<w_lista->index<<endl;
     }

     cout<<"Ktory element struktury chcesz aby zostal usuniety?: ";
     cin>>ilosc;

     Usun(w_lista, ilosc);

     while(w_lista != NULL)
     {
          if(w_lista !=NULL)
               cout<<w_lista->index<<endl;

          w_lista = w_lista->w_n_statek;
     }

     return 0;
}

void Usun(WrogiStatek* w_lista, int ilosc)
{
     WrogiStatek* tymczas;

     while(w_lista != NULL)
     {
          if(w_lista->w_n_statek->index == ilosc)
          {
                tymczas = w_lista->w_n_statek->w_n_statek;
               delete w_lista->w_n_statek;
               w_lista->w_n_statek = NULL;
               w_lista->w_n_statek = tymczas;
               break;
          }else
          if(w_lista->index == ilosc)
          {
               delete w_lista;
               w_lista = w_lista->w_n_statek;
               w_lista = NULL;
               break;
          }
          w_lista = w_lista->w_n_statek;
     }
}

Zrozumiecie o co mi chodzi jeśli wpiszecie do programu np.

5 i 1 lub 2 lub 3 lub 4(wybierzcie jedną z tych liczb)

Kolejnym razem gdy uruchomicie program podajcie te same liczby np:

5 i 5 

lub 

10 i 10

Wtedy wszystko się wyjaśni

komentarz 14 lipca 2016 przez obl Maniak (51,280 p.)
Zrobiłeś stos, i próbujesz usunąć i-ty element jego?
komentarz 14 lipca 2016 przez SebekMakaron Obywatel (1,290 p.)
Tak, mam takie zadanie. Element stosu usuwam ale nie wiem dlaczego wyświetla się mając wartość NULL. Dotyczy to tylko pierwszego elementu jeśli odpalałeś program wiesz o co chodzi. Masz jakieś cenne wskazówki jak to zmienić?
komentarz 14 lipca 2016 przez obl Maniak (51,280 p.)

Funkcja Usuń dla próby usunięcia pierwszego elementu zakończy się niepowodzeniem, ponieważ wewnątrz tej funkcji (gdy wybierasz pierwszy element stosu) zwalniasz pamięć, do której wskaźnik w funkcji main przechowujesz a później próbujesz się odwołać do już zwolnionej pamięci. Ja to poprawiłem tak:

WrogiStatek* Usun(WrogiStatek* w_lista, int ilosc){
	WrogiStatek* first = w_lista;
     WrogiStatek* tymczas;

	 if(w_lista->index == ilosc)
		 first = w_lista->w_n_statek;
 
     while(w_lista != NULL)
     {
          if(w_lista->w_n_statek != NULL && w_lista->w_n_statek->index == ilosc)
          {
                tymczas = w_lista->w_n_statek->w_n_statek;
               delete w_lista->w_n_statek;
               w_lista->w_n_statek = NULL;
               w_lista->w_n_statek = tymczas;
               break;
          }else
          if(w_lista->index == ilosc)
          {
			  tymczas = w_lista->w_n_statek;
               delete w_lista;
               w_lista = tymczas;
		  }
          w_lista = w_lista->w_n_statek;
     }
	 return first;
}

I w funkcji main:

w_lista = Usun(w_lista, ilosc);

 

+1 głos
odpowiedź 13 lipca 2016 przez obl Maniak (51,280 p.)

Wszędzie gdzie pamięć alokowana jest za pomocą operatora new powinna być ona zwalniana za pomocą operatora delete. Dodatkowo po delete powinno się wykonać:

int *zmienna = new int;
if(zmienna){
    delete zmienna;
    zmienna = NULL;
}

żeby było wiadomo kiedy wskaźnik ma przydzieloną pamięć. Moim zdaniem nie warto używać struktur do przechowywania zmiennych alokowanych dynamicznie, bo łatwo jest zapomnieć o zwolnieniu takiej pamięci. W klasach możesz sobie to obsłużyć raz w destruktorze i po problemie a w strukturach musisz cały czas o tym pamiętać.

komentarz 15 lipca 2016 przez SebekMakaron Obywatel (1,290 p.)
A co w przypadku kiedy tworze dynamiczny wskaźnik w funkcji i nie mogę usunąć go na końcu tej funkcji ponieważ zawarta jest w nim "informacja" dzięki której po powrocie do głównej funkcji main() program może właściwie działać.

Czy w takiej sytuacji powinienem za wszelka cenę starać się usunąć go na końcu funkcji czy usunąć go w funkcji main() ale pod postacią którą zwrócił ten wskaźnik.

Przepraszam jeśli wyrażam się skomplikowanie ale nie ma talentu do przekazu. Zadaj pytanie które pozwoli mi stwierdzić czego nie za bardzo rozumiesz a ja postaram się wytłumaczyć to bardziej przejrzyście lub podam przykład.
komentarz 15 lipca 2016 przez obl Maniak (51,280 p.)
Jeżeli wskaźnik do pamięci będzie przechowywany i wykorzystywany poza funkcją to musisz tylko pamiętać o zwolnieniu pamięci, gdy ta już nie będzie ci potrzebna. Innymi słowy możesz to zrobić w dowolnym miejscu (nawet poza funkcją, w której tą pamięć przydzieliłeś) ważne żebyś miał możliwość po zakończeniu funkcji operowania na wskaźniku do przydzielonej w niej pamięci.
+1 głos
odpowiedź 13 lipca 2016 przez Patrycjerz Mędrzec (192,320 p.)

Oczywiście, że musisz. Struktura to nic innego, jak zbiór danych, czyli stałych i zmiennych. Jeśli zwracasz taki wskaźnik, to musisz pogodzić się z tym, że to, na co wskazuje, prędzej czy później, usuniesz delete.

Popatrz np. na obsługę pliku w bibliotece standardowej C - masz tam funkcję fopen, która zwraca wskaźnik FILE, lecz później używasz funkcji close, która zamyka plik, czyli m.in. zwalnia pamięć.

Podobne pytania

0 głosów
1 odpowiedź 122 wizyt
pytanie zadane 12 czerwca 2020 w C i C++ przez dominik195k Obywatel (1,030 p.)
0 głosów
0 odpowiedzi 549 wizyt
pytanie zadane 12 lipca 2021 w JavaScript przez _Visni4PL_ Obywatel (1,320 p.)
0 głosów
2 odpowiedzi 331 wizyt
pytanie zadane 23 czerwca 2021 w C i C++ przez Eriss69 Gaduła (4,470 p.)

92,579 zapytań

141,429 odpowiedzi

319,657 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...