Ogólnie rozumiem jak działa destruktor dla obiektow, zmiennych dynamicznych itp ale mam problem z tym czy zmienna wskaźnikowa jest usuwana automatycznie czy trzeba uzyc delete. np gdy mam pole w klasie
char *napis;
to w destuktorze powinienem mieć
delete [] napis;
a jak to wyglada dla innych typów zmiennych np
int *liczba;
czy dla wskaznika na inta tez musze usuwac zmienna w destruktorze czy zostanie ona usunieta po "wyskoczeniu" poza obszar widocznosci jak to jest z np int a;?
Chyba nie do końca rozumiesz działania zmiennych dynamicznych. To czy trzeba zwolnić pamięć zależy czy ją alokowałeś. Jeżeli gdzieś w kodzie masz powiedzmy int *a = new int; to musisz w miejscu, w którym już ta zmienna int nie jest potrzebna zrobić delete a;
Po wyjściu za zakres obowiązywania co najwyżej zostanie usunięty wskaźnik, ale nie to na co pokazywał.
no tak np char *napis; alokuje obszar pamieci na tablice znakow i trzeba ta "tablice" usunac w destruktorze, a jak to jest z int *liczba;? bo Twoja odpowiedz nie dala jednoznacznej odpowiedzi na moje pytanie albo czegos bardzo mocno nie rozumiem
char napis; NIE alokuje pamięci na tablicę znaków, ale tworzy zmienną typu char (wskaźnik do zmiennych typu char) na stosie. Alokacja pamięci na tablicę znaków w takim wypadku wygląda np. tak: char *napis = new char[20];. Dopiero po zaalokowaniu pamięci możesz zrobić delete [] napis, w innym wypadku jak będziesz miał szczęście to program się wysypie, jak nie będziesz miał farta to może się to objawić dziwnymi błędami i przyczynę będzie bardzo ciężko znaleźć.
W ogólności dla każdego new/new[] musi być odpowiadające mu delete/delete[].
Ponadto dla typów wbudowanych nie ma destruktorów. Destruktor może mieć obiekt złożony(klasa).
Dla typów wbudowanych, jest konstruktor i destruktor
ściślej: tak jakby były. takie coś zadziała:
int i(3); // to samo co: int i=3;
int j(i); // to samo co: int j=i;
int k(); // nawiasy opcjonalne
int *l = new int(3); // to samo co: int *l=new int; *l=3;
int *m = new int(); // nawiasy opcjonalne
najnowszy standard będzie dopuszczał także nawiasy klamrowe:
int o{4}; // int o=4;
int p = {4}; // int p=4;
int r{}; // int r=0;
int s = {}; // int s=0;
int *t = new int{4}; // int *t=new int; *t=4;
proszę tu zwrócić uwagę, że int x()
to to samo co int x
, ale int x{}
to to samo co int x=0
.
Azarien napisał(a)
proszę tu zwrócić uwagę, że
int x()
to to samo coint x
, aleint x{}
to to samo coint x=0
.
Ściślej to pierniczysz waść w całej rozciągłości. int x();
to deklaracja bezargumentowej funkcji zwracającej int
, int x;
to deklaracja zmiennej typu int
. int x{};
to w ogóle niepoprawna konstrukcja, typy proste nie są agregatami.
Azarien napisał(a)
int k(); // nawiasy opcjonalne
int *m = new int(); // nawiasy opcjonalne
W tych przypadkach nawiasy mają bardzo określone znaczenie.
int k();
- jest to deklaracja funkcji bezargumentowej
k()
zwracającejint
- nie jest to deklaracja zmiennej.
int* m = new int();
Tutaj dzięki nawiasom *m == 0
int* n = new int;
A tutaj już bez nawiasów - *n
ma wartość nieokreśloną.
int x;
więc jest czymś kompletnie innym niż int x();
, które znów są czymś innym niż (błędne w C++03) int x = {}
. :)
macie rację co do funkcji. łatwa pułapka.
ale co do {}, to - jak napisałem - jest to dozwolone w nowym standardzie (C++0x), i ma konkretne znaczenie. zostało to wprowadzone, by agregatami stało się znacznie więcej typów, np.
vector<int> w = {1,2,3,4};
zatem w przypadku zmiennej lokalnej
int k; // wartość nieokreślona
int k = 0;
int k(0);
int k = {}; // C++0x, wartość 0
int k = {0}; // C++0x, wartość 0
wracając do pierwotnego pytania
czy dla wskaznika na inta tez musze usuwac zmienna w destruktorze czy zostanie ona usunieta po "wyskoczeniu" poza obszar widocznosci jak to jest z np int a;?
sam wskaźnik wychodzi poza zasięg więc jest usuwany. Ale wskazywany obszar, jeśli był przydzielony przeznew
, automatycznie zniszczony nie zostanie (więc bezdelete
będzie stanowić „wyciek pamięci”)