[ LUGOS-PROG ] Klicanje destruktorja razreda

Goran Bervar goran.bervar at adapti.si
Wed Aug 22 13:42:38 CEST 2001


----- Original Message -----
From: "Ales Bardorfer" <alesb at robo.fe.uni-lj.si>
To: <lugos-prog at lugos.si>
Sent: Monday, August 20, 2001 6:28 PM
Subject: Re: [ LUGOS-PROG ] Klicanje destruktorja razreda


> > btw Exit(0) tukaj ni potreben, oziroma moras namesto njega napisati
> > return 0.
>
> Malo sem eksperimentiral v dobri veri, da bom priklical destruktor...
> Sicer pa..., seveda se za int funkcijo spodobi, da kaksen int tudi vrne.

Hja, imas cisto prav. Razen za 'main', kjer standard dovoljuje da ne napises
retrun stavka, prevajalnik mora reagirati kot da si napisal 'return 0'. Z
drugimi besedami, spodobi se in pravicno je ce main ne vraca vrednosti.

Samo se nekaj razlage o destruktorjih pa ce jo rabis ali ne:

Prevajlnik klice destruktor, ko se objekt unici. Lokalna (avtomatska)
spremenljvika se unici, ko ni vec v dosegu. Prevajalnik mora uniciti objekt
zato klice destruktor, na primer:

int destest()
    {
    razred A;


        razred B;
        } /* tule nekje gre B iz dosega, klice se B.~razred(); */
    return 0;
    }/* tule nekje gre A iz dosega, klice se A.~razred(); */

Podobno velja za globalne spremenljivke. Preden program konca z delom, mora
pospraviti za sabo, zato nekje med zadnjim zaklepajem funkcije main in
dejanskim koncem pregrama prevajlnik klice destruktor, na primer:

razred G;

int main()
    {
    } /* nekje za tem oklepajem bo prevajlnik unicil G , klice se
G.~razred(); */

V tem primeru moras biti malo pozoren. Kot za vse globale na splosno velja,
da vrstni red unicevanja globalov ni dolocen. Zato ti lahko destruktor, ki
uporablja kak drug global ( na primer std::cout) dela pravo zgago.

Dinamicne spremenljivke so pac dinamicne. Ker jih moras kreirati sam z 'new'
jih moras tudi unicti sam z 'delete'. Prevajalnik noce in ne sme vedeti
koliko casa je dinamicna spremenljivka veljavana. Se pravi, da se bo
destrukor za dinamicno spremenljivko klical samo v primeru, ko ti z 'delete'
unicis objekt, na primer:

int destroy(razred* r)
    {
    delete r; /*klice destruktor r->~razred() objekta, na katerega kaze r*/
    }

int main()
    {
    razred* dA = new razred;
    razred* dB = new razred;
    razred* dC = new razred;

    destroy(dA); /* tale klice funkcijo, ki unici dA. Ko funkcija vrne -
pravzaprav se prej - kaze dA  na neveljavno lokacijo*/
    delete dB; /* preden zares pobrise dinamicno alociran spomin, klice
destruktor dB->~razred() */
    }

*dC ostane nedotaknjen ker sem ga 'pozabil' uniciti z delete. Temu recemo
"puscanje spomina" ( v anglescini "memory leak" ) in je nekaj JAKO groznega.
Upam da to ves - ce ne, se hitro nauci da se ne bos kasneje cudil fantomskem
obnasanju tvojih programov.

Funkciji exit() in abort() sta pa zivi grozi v C++ programu.

Funkcija abort() "takoj" prekine izvajanje programa. Prevajalnik *ne bo*
klical destruktorjev se zivih objektov ne glede na to ali so globalni
(staticni),  loklani( avtomatski ) ali dinamicni. Da o kaksnem sporscevanju
spomina sploh ne govorimo. Skratka, funkcija panicno prekine program ne da
bi pogledala levo in desno.

Funkcija exit() je nacelno namenjena "normalni" prekinitvi C programa
kjerkoli jo pac klices. V C++ je malce nevarna in zato bolj kot ne
neuporabna, ker ne bo klicala destruktrojev vseh se zivih objektov. Klicali
se bodo destruktorji globalnih (staticnih) objektov, ne pa tudi lokalnih
objketov ce je bil kateri narjen na poti klicanja funkcije exit(). In
seveda, za noben dinamicni objekt se ne bo klical destruktor ali sprostil
spomin.

Vsak posten operacijski sistem bo sicer poskrbel, da ne bodo tvoji objekti
tavali po spominu ce nasilno prekines program z exit() ali abort() ampak
resno, ne uporabljaj ju v C++ za karkoli drugega kot panicen pobeg iz
programa ob kaki strasni napaki.

Se primer - kar poskusi ga!

#include <iostream>
#include <string>
#include <cstdlib>

class test
    {
    std::string desc;
    public:
    test(std::string d) : desc ( d ){}
    ~test() { std::cout << desc << " destructor called << std::endl; }
    };

test G("Global ");
test* pgD2;

void postMain(void)
    {
    delete pgD2;
    }

int main()
    {
    atexit(postMain); /* poglje man za atexit */

    test A("Automatic");
    test* pD1 = new test("Dynamic 1");
    test* pgD2 =  new test("Dynamic 2");
    std::cout<<"0 ... return" << std::endl
            <<"1 ... abort" << std::endl
            <<"2 ... exit" << std::endl;
    int rv = 0 ;
    cin >> rv;
    if( rv == 1)
        abort();
    if( rv == 2)
        exit();
    delete pD1;
    return 0;
    }

Upam da se prevede - sem prelen da bi pozkusil.

goran








More information about the lugos-prog mailing list