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

Tajemnicza struktura i delete

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
–1 głos
455 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,300 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,300 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,300 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,300 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ź 183 wizyt
pytanie zadane 12 czerwca 2020 w C i C++ przez dominik195k Obywatel (1,030 p.)
0 głosów
0 odpowiedzi 852 wizyt
pytanie zadane 12 lipca 2021 w JavaScript przez _Visni4PL_ Obywatel (1,320 p.)
0 głosów
2 odpowiedzi 765 wizyt
pytanie zadane 23 czerwca 2021 w C i C++ przez Eriss69 Gaduła (4,470 p.)

93,439 zapytań

142,431 odpowiedzi

322,677 komentarzy

62,802 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

...