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

[C++] Pytanie o życie destruktora

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
+1 głos
892 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 (214,530 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 (214,530 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 (214,530 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ź 266 wizyt
pytanie zadane 7 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
0 głosów
2 odpowiedzi 961 wizyt
pytanie zadane 19 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
0 głosów
1 odpowiedź 182 wizyt
pytanie zadane 30 marca 2020 w C i C++ przez Quegon23 Nowicjusz (150 p.)

93,185 zapytań

142,198 odpowiedzi

322,005 komentarzy

62,514 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2127p. - dia-Chann
  2. 2092p. - Łukasz Piwowar
  3. 2079p. - Łukasz Eckert
  4. 2037p. - Tomasz Bielak
  5. 2006p. - rucin93
  6. 2005p. - Łukasz Siedlecki
  7. 1964p. - CC PL
  8. 1835p. - Adrian Wieprzkowicz
  9. 1785p. - Michal Drewniak
  10. 1744p. - rafalszastok
  11. 1684p. - Mikbac
  12. 1624p. - Anonim 3619784
  13. 1520p. - Marcin Putra
  14. 1480p. - ssynowiec
  15. 1365p. - Dawid128
Szczegóły i pełne wyniki

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...