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

wywoływanie destruktora.

Object Storage Arubacloud
+1 głos
347 wizyt
pytanie zadane 20 grudnia 2020 w C i C++ przez dominik195k Obywatel (1,030 p.)

Cześć, czy wie ktoś czy można "panować" nad wywoływaniem destruktora? Destruktor wywołuje się w momencie niszczenia obiektu, czyli również w czasie trwania programu np. kiedy wywołujemy funkcje w której tworzymy obiekt klasy posiadającej destruktor. Chciałbym żeby destruktory tych obiektów(z funkcji) były wywoływane na końcu programu, czy jest to możliwe?

#include <iostream>
using namespace std;

class klasa {
private: 
	int* x;
public:
	klasa()
	{
		x = new int[3];
	}
	klasa& fun()
	{
		klasa A;
		return A;
	}
	~klasa()
	{
		delete x;
		cout << " usunieto " << endl;
	}
};
int main()
{
	klasa B;
	B.fun();
// wywolanie destruktora 1
	B.fun();
// wywolanie destruktora 2

	return 0;
// wywolanie destruktora obiektu B
// i tutaj chcialbym zeby byly wywolane destruktory 1 i 2
}

Przykładowy program pokazujący o co chodzi

komentarz 21 grudnia 2020 przez VBService Ekspert (253,300 p.)
edycja 21 grudnia 2020 przez VBService

Według opisu @mokrowski i @profesorek96 wink


#include <iostream>
using namespace std;
  
class moja_klasa {
    private: 
        int* x;
        char* ch_;
    public:
        moja_klasa(char ch) {
            x = new int[3];
            ch_ = new char(ch);
            cout << "Konstruktor dla: " << ch_ << endl;
        }
        moja_klasa& fun()
        {
            cout << " wywolano fun() dla: " << ch_ << endl;
            return *this;
        }
        ~moja_klasa()
        {
            delete [] x;
            cout << "Destruktor dla: " << ch_ << endl;
        }
};
    
int main()
{
    moja_klasa *a = new moja_klasa('a');
    a->fun();
    // wskazówka: @profesorek96
    // wywołanie destruktora - "świadome"
    // musi nastąpić po użyciu operatora new
    // zapobieganie "wyciekaniu pamięci"
    delete a;
    
    cout << endl;
    
    moja_klasa b('b');
    moja_klasa c('c');
    b.fun();
    c.fun();
    
    cout << "\nKoniec programu\n";
    
    // // wskazówka: @mokrowski
    // tu następuje automatyczne zniszczenie (wywołanie destruktora)
    // w odwrotnej kolejności niż kreacja.
    // czyli c, później b
    
    return 0;
}

 

3 odpowiedzi

+1 głos
odpowiedź 20 grudnia 2020 przez mokrowski Mędrzec (155,460 p.)

Ależ one w podanym przykładzie, właśnie są wywoływane na końcu programu:

#include <iostream>
using namespace std;
 
class klasa {
private: 
    int* x;
public:
    klasa()
    {
        x = new int[3];
    }
    klasa& fun()
    {
        return *this;
    }
    ~klasa()
    {
        delete [] x;
        cout << " usunieto " << endl;
    }
};
int main()
{
    klasa a;
    klasa b;
    a.fun();
    b.fun();
    cout << "Koniec programu\n";
    // Tu następuje zniszczenie w odwrotnej kolejności niż kreacja.
    // Czyli b a później a
}

 

komentarz 20 grudnia 2020 przez dominik195k Obywatel (1,030 p.)
#include <iostream>
using namespace std;

class klasa {
private: 
	int* x;
public:
	klasa()
	{
		x = new int[3];
	}
	klasa& fun()
	{
		klasa A;
		return A;
	}
	~klasa()
	{
		delete x;
		cout << " usunieto " << endl;
	}
};
int main()
{
	int a;
	klasa B;
	B.fun();
	B.fun();
	cin >> a;

	return 0;
}

No właśnie że nie zobacz że zanim wprowadzisz jakąś liczbę do 'a' już pojawiają się 2 komunikaty "usunięto" dotyczące dwukrotnego wywołania funkcji.

komentarz 20 grudnia 2020 przez mokrowski Mędrzec (155,460 p.)
edycja 20 grudnia 2020 przez mokrowski
Możesz sprawdzić czym różni się mój kod od Twojego?

Co masz w linii 14 swojego kodu?

A linia 19? Jak usuwasz tablicę?
+1 głos
odpowiedź 21 grudnia 2020 przez profesorek96 Szeryf (91,420 p.)

Zacznijmy od tego że w języku C++ mamy cztery rodzaje pamięci:

  • Pamięć automatyczn
  • Pamięć dynamiczn
  • Pamięć statyczn
  • Pamięć wątku

Pamięci wątku oraz statycznej nie będę omawiał. Zajmiemy się tylko pamięcią automatyczna i dynamiczną. Pierwsza z nich czyli pamięć automatyczna to nic innego jak zmienne „zwykłe” czyli np int x, zmienna  x należy do pamięci automatycznej, tak samo Moja_klasa k to również pamięć automatyczna. Pamięć ta charakteryzuje się tym że zmienne należące do tego rodzaju pamięci są automatycznie usuwane po wyjściu z bloku kodu lub funkcji.
Pamięć dynamiczna to wszystko co tworzymy za pomocą operatora new, zmienne, obiekty będą żyły, zajmowały zasoby dopóki nie zostanie pamięć na nasze życzenie zwolniona za pomocą operatora delete.

Oczywiści zasoby zarezerowane za pomocą new zostaną zwolnione przez system po zakończeniu programu.

Weźmy taki program:

#include <iostream>
using namespace std;    

class Moja_klasa
{
    public:
    Moja_klasa()
    {
        cout<<"Konstruktor"<<endl;
    }
    ~Moja_klasa()
    {
        cout<<"Destruktor"<<endl;
    }
};
int main()
{
    Moja_klasa moja;
    return 0;
}

Uruchamiając ten program naszym oczom ukaże się napis Konstruktor, a zaraz pod nim Destruktor. W funkcji main tworzymy obiekt  moja, dlatego wywołuje się konstruktor zaś zaraz po tym funkcja main się kończy więc nasz obiekt jest niszczony.
Proponuję teraz zmodyfikować nasz program na taki:

#include <iostream>
using namespace std;    

class Moja_klasa
{
    public:
    Moja_klasa()
    {
        cout<<"Konstruktor"<<endl;
    }
    ~Moja_klasa()
    {
        cout<<"Destruktor"<<endl;
    }
};
int main()
{
    Moja_klasa *moja=new Moja_klasa();
    return 0;
}

W tym przypadku tworzymy obiekt dynamicznie za pomocą operatora new. Jak pewnie zauważyłeś na standardowe wyjście wypisuje się tylko napis Konstruktor oznaczający ze tylko konstruktor został wykonany. Jest to jak najbardziej normalne, operator new powoduje wysłanie konstruktora. Jeśli chcieli byśmy zwolnić zasoby, zarazem wywołać destruktor powinniśmy użyć operatora delete. Zobaczymy więc na kolejny przykład:

#include <iostream>
using namespace std;    

class Moja_klasa
{
    public:
    Moja_klasa()
    {
        cout<<"Konstruktor"<<endl;
    }
    ~Moja_klasa()
    {
        cout<<"Destruktor"<<endl;
    }
};
int main()
{
    Moja_klasa *moja=new Moja_klasa();
    delete moja;
    return 0;
}

Teraz naszym oczom powinien ukazać się zarówno napis Konstruktor jak i Destruktor. Zasadniczo konstruktor jest to metoda która „konfiguruje”, przygotowuje nasz obiekt do działania, istnienia. Zaś destruktor to metoda która sprząta po obiekcie, to właśnie w nim powinna znaleść się realokacja pamięci zablokowanej przez konstruktor czy zakończenia połączenia z bazą danych.
Operator new jak i delete stanowią parę, pierwszy z nich wywołuj konstruktor zaś drugi destruktor. Ponadto odpowiednio rezerwują pamięć, oraz ja dealokują. Nigdy nie wolno mieszać operatora new i delete z funkcjami pochodzącymi z języka C takimi jak malloc, calloc, realloc czy free. Jeśli tworzymy obiekt za pomocą new nie możemy go usunąć funkcja free, to samo jeśli tworzymy obiekt funkcją malloc nie możemy go zwolnić operatorem delete. Nie zwolnienie zasobów stworzonych w pamięci dynamicznej może skutkować wyciekiem pamięci. Pamiętaj również że jednemu operatorowi new powinien odpowiadać jeden operator delete. Nie można kilkakrotnie usuwać już zwolnione pamięci jak i tworzyć kilkukornie nowego obszaru pamięci bez uprzednio zwolnienia starego.

0 głosów
odpowiedź 20 grudnia 2020 przez Kabuuz Bywalec (2,820 p.)
Ogólnie to destruktor możesz wywołać sam ale i tak on zostanie wywolany przy wyjściu zmiennej ze scope'u. Jakbyś chciał żeby ta klasa B odpowiadała za tworzenie tych obiektów i żeby z nią je zniszczyć to musiałbyś dodawać te obiekty np. jako smartpointery do jakiejś tablicy w  klasie B i zwracać do nich referencje. Wtedy te obiekty nie zginą póki B nie zostanie usunięte.

Podobne pytania

0 głosów
1 odpowiedź 154 wizyt
0 głosów
3 odpowiedzi 175 wizyt
+1 głos
3 odpowiedzi 527 wizyt
pytanie zadane 25 sierpnia 2016 w C i C++ przez JAKUBW Nałogowiec (33,470 p.)

92,568 zapytań

141,420 odpowiedzi

319,620 komentarzy

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

...