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

[C++] Pytanie o życie destruktora

Object Storage Arubacloud
+1 głos
526 wizyt
pytanie zadane 25 sierpnia 2016 w C i C++ przez JAKUBW Nałogowiec (33,470 p.)

Mam pytanie dotyczące czasu istnienia destruktora w klasie.

Do moich testów stworzyłem kod:

#include <iostream>
#include <vector>

using namespace std;
class Klasa;

std::vector <Klasa *> tab;

class Klasa
{
public:
   int x;
   void foo() { delete this; }
   Klasa(){ x = 5; }
   ~Klasa()
   {
      cout<<"Niszczenie... x = "<<x<<endl;
   }
};

int main()
{
   for(std::size_t i = 0;i<3;i++)
      tab.push_back(new Klasa);

   tab[1]->foo();
   
   cout<<"tab[1]->x wynosi: "<<tab[1]->x<<endl<<endl;

   cout<<"Destruktory:"<<endl;
   for(std::size_t i = 0;i<3;i++)
      delete tab[i];
   return 0;
}

I zauważyłem pewien problem: mimo, że usunąłem obiekt (przez delete this) jego destruktor nadal żyje (spodziewałem się crashu aplikacji(odwołanie do nieistniejącego obiektu)), lecz składowe klasy są już inne.

Moje pytanie brzmi:

Czy używając delete this zwalniam pamięć oraz dlaczego destruktor nadal "żyje"?

3 odpowiedzi

+1 głos
odpowiedź 25 sierpnia 2016 przez Ehlert Ekspert (212,670 p.)
wybrane 27 sierpnia 2016 przez draghan
 
Najlepsza
  1. You must be absolutely 100% positively sure that this object was allocated via new (not by new[], nor by placement new, nor a local object on the stack, nor a namespace-scope / global, nor a member of another object; but by plain ordinary new).
  2. You must be absolutely 100% positively sure that your member function will be the last member function invoked on this object.
  3. You must be absolutely 100% positively sure that the rest of your member function (after the delete this line) doesn’t touch any piece of this object (including calling any other member functions or touching any data members). This includes code that will run in destructors for any objects allocated on the stack that are still alive.
  4. You must be absolutely 100% positively sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with nullptr, print it, cast it, do anything with it.

isocpp.org

1
komentarz 26 sierpnia 2016 przez MetRiko Nałogowiec (37,110 p.)

Jeżeli używasz C::B to spróbuj tego: Link

1
komentarz 26 sierpnia 2016 przez draghan VIP (106,230 p.)

Hmm, a wytłumaczy mi ktoś dlaczego mimo ustawienia na NULL to działa?

#include <iostream>

using namespace std;

class Klasa
{
public:
   void foo() { cout<<"12"<<endl;}
};
int main()
{
   Klasa *o = new Klasa;

   delete o;
   o = NULL;

   o->foo();//nadal dziala

   if(o == NULL)
      cout<<"obiekt usunienty"<<endl;
   else
      cout<<"obiekt istnieje"<<endl;

   //delete o; //"teoretycznie" juz go usunalem
   return 0;
}

Czyżby obiekt nadal istniał?

Nie, obiekt nie istniał. Metody obiektu traktowane są nieco inaczej, niż zmienne instancyjne. Zauważ, że metody nie są odrębne dla każdego obiektu, a są wspólne dla klasy.

Stąd, mając informację o typie danej klasy (a wskaźnik przecież takie informacje posiada), MOŻESZ się odwołać wskaźnikiem do metody obiektu.

Ale nie powinieneś tego robić. Wszystkie zmienne obiektu znajdują się pod adresami niedozwolonymi już dla Twojej aplikacji (poprzez delete powiedziałeś systemowi żeby oznaczył tę pamięć jako wolną).

komentarz 26 sierpnia 2016 przez JAKUBW Nałogowiec (33,470 p.)

To wszystko tłumaczy - obiekt nie istnieje, ale mogę użyć jego metod, lecz nie powinienem, bo zmienne tego obiektu zostały już usunięte. A destruktor "żyje", ponieważ to nadal metoda. Dziękuję wszystkim za pomoc.

komentarz 26 sierpnia 2016 przez Ehlert Ekspert (212,670 p.)

destruktor nie żyje. Może być co najwyżej callable

5
komentarz 26 sierpnia 2016 przez draghan VIP (106,230 p.)

destruktor nie żyje

0 głosów
odpowiedź 25 sierpnia 2016 przez niezalogowany
co masz na myśli że nadal żyje
komentarz 25 sierpnia 2016 przez JAKUBW Nałogowiec (33,470 p.)
Działa i nie wywołuje crashu a wydaje mi się, że powinien. W końcu usunąłem już jego obiekt.
–2 głosów
odpowiedź 25 sierpnia 2016 przez Michał Muzyka Pasjonat (24,080 p.)

ale wiesz, że

delete this;

nie wywołuje destruktora, bo nie usuwa danego obiektu

komentarz 25 sierpnia 2016 przez Ehlert Ekspert (212,670 p.)
Co to za bzdury?
komentarz 25 sierpnia 2016 przez draghan VIP (106,230 p.)

ale wiesz, że

delete this;

nie wywołuje destruktora, tylko usuwa wskaźnik na klasę

Ściślej mówiąc - usuwa wskaźnik na instancję klasy*. A w kwestii, czy nie wywołuje destruktora, polecam przetestować poniższy kodzik:

#include <iostream>

class Foo
{
public:
    ~Foo()
    {
        std::cout<<"Destruktor";
    }
    void delete_this()
    {
        delete this;
    }
};

int main()
{
    Foo *f = new Foo;
    f -> delete_this();

    char wait;
    std::cout<<"Czekam na pobranie znaku by zakończyć program\n";
    std::cin.get(wait);
    return 0;
}

*- też jestem nieprecyzyjny. Nie usuwa wskaźnika - wskaźnik nadal sobie w programie istnieje. Operator delete po prostu zwalnia fragment pamięci, wskazywany przez wskaźnik. Zaś sam wskaźnik może pokazywać jedynie instancję klasy, czyli obiekt. Składając to do kupy: delete może zwolnić pamięć, zajmowaną przez obiekt. I oczywiście destruktor zostanie wywołany - tym przede wszystkim delete z C++ różni się od free() z C.

komentarz 26 sierpnia 2016 przez Michał Muzyka Pasjonat (24,080 p.)
przepraszam, zrozumiałem swój błąd, zasugerowałem się, źle zinterpretowanym kodem z innej strony

Podobne pytania

0 głosów
1 odpowiedź 223 wizyt
pytanie zadane 7 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
0 głosów
2 odpowiedzi 458 wizyt
pytanie zadane 19 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
0 głosów
1 odpowiedź 145 wizyt
pytanie zadane 30 marca 2020 w C i C++ przez Quegon23 Nowicjusz (150 p.)

92,555 zapytań

141,403 odpowiedzi

319,554 komentarzy

61,939 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!

...