dynamiczna alokacja a destruktor

0

Hey, mam następujący problem:
Stworzyłem klasę, w której deklaruję wskaźnik w celu stworzenia dynamicznej tablicy.
Jak wiadomo, gdy będę chciał usunąć obiekt takiej klasy to w destruktorze powinienem zwolnić zaalokowaną pamięć.
Problem w tym, że nie zawsze jest konieczna taka alokacja (czasami wskaźnik wskazuje na nic) i nie mogę usunąć pamięci, jeśli wcześniej jej nie zaalokowałem.
Przykładowo klasa wygląda to tak:

class klasa
	{
        public:
	double* wsk;
	void tworz_tablice(int i){wsk = new double[i];} //funkcja opcjonalna
	~klasa(){delete[] wsk;}	//a co jeśli nie będzie zaalokowana pamięć?!?
	}

Czy da się jakoś sprawdzić czy była wcześniej alokowana pamięć?

Z góry dziękuję za pomoc w rozwiązaniu mojego dylematu.

0

Okey, chyba znalazłem odpowiedź, ale bardzo proszę o potwierdzenie!
Wystarczy inicjalizować taki wskaźnik wartością NULL lub nullptr - np. w konstruktorze. Wówczas w destruktorze można sprawdzić przed delete czy wskaźnik nie jest null. Z drugiej strony nic złego się nie stanie jak usunie się wskaźnik pokazujący na NULL...

Drugie pytanie jakie zaczęło mnie nurtować to czy jeśli miałbym tablicę 2 wymiarową w klasie to czy zasada jest analogiczna i wystarczy do wskaźnika przypisać null czy również muszę dać null na wskaźnik na wskaźnik? tzn. chodzi mi o to czy poniższy kod jest poprawny:

double** wsk = nullptr; //wskaźnik na wskaźnik - ustawiamy na NULL (by w razie czego nie usunąć czegoś niepotrzebnie)

//tworzymy (lub nie) tablicę dwuwymiarową
wsk = new double*[dim1];
for(i=0; i<dim1; i++)
wsk[i] = new double[dim2];

//usuwanie pamięci
if(wsk) //najpierw sprawdzamy czy wskaźnik nie jest pusty - tj. czy został w jakiś sposób wykorzystany
{
for(i=0; i<dim1; i++)
delete[] wsk[i];
delete[] wsk;
}

Z góry dziękuję za rozjaśnienie mi tej kwestii!

0

Jeżeli na początku (w konstruktorze) ustawisz wartość tego wskaźnika na nullptr to takie rozwiązanie będzie dobre. W przypadku podwójnego wskaźnika nie możesz pominąć sprawdzania, bo musisz wiedzieć, czy jest po czym iterować, żeby to usuwać.

Zastanów się jednak, czy to już konstruktor nie powinien alokować tego miejsca.

0
Endrju napisał(a):

Jeżeli na początku (w konstruktorze) ustawisz wartość tego wskaźnika na nullptr to takie rozwiązanie będzie dobre. W przypadku podwójnego wskaźnika nie możesz pominąć sprawdzania, bo musisz wiedzieć, czy jest po czym iterować, żeby to usuwać.

Zastanów się jednak, czy to już konstruktor nie powinien alokować tego miejsca.

Chodzi Ci o to, że to powinno wyglądać tak - jeśli się nie mylę:

if(wsk) //najpierw sprawdzamy czy wskaźnik na wskaźnik nie jest pusty
{
for(i=0; i<dim1; i++)
{
if(wsk[i]) //a tutaj sprawdzam czy drugi wymiar na coś nie pokazuje
delete[] wsk[i];
}

delete[] wsk;
}

Zgadza się?

Niestety w konstruktorze nie mogę alokować pamięci, bo nie zawsze będę chciał to robić i potrzebuję najpierw znać wymiar tej tablicy - ciężko mi tak na szybko wytłumaczyć co chcę zrobić ;-).

Dzięki wielkie Endrju!

0

Zastanów się czy nie potrzebujesz własnego konstruktora kopiującego oraz operatora przypisania.

0
Rev napisał(a):

Zastanów się czy nie potrzebujesz własnego konstruktora kopiującego oraz operatora przypisania.

Tak, chyba masz rację - coś zaczyna mi świtać, że coś takiego było zalecane w książce ;)

Mam jednak jeszcze jedno pytanie:
Jak ustawiam wskaźnik na wskaźnik na nullptr o tak:
double** wsk = nullptr;
to czy nie powinienem "jakoś" dodatkowo ustawić nullptr na wskaźnik w 1 wymiarze?
Bo w innym wypadku bez zaalokowania pamięci wskaźnik na wskaźnik ma wartość NULL, ale wskaźnik (1 dim) ma chyba jakieś śmieci? Czy nie?
Bo zacząłem się zastanawiać czy jest sens przed deletowaniem sprawdzać czy: if(wsk[i]) - jeśli ja ustawiłem NULL tylko na wsk...
Mam nadzieję, że jestem rozumiany ;-)

Chodzi o to, że mogę zaalokować tablicę wskaźników, ale nie zaalokować tablicy wskaźników na wskaźnikach i przy kasowaniu może wywalić mi błąd...

0

Zależy. Jeśli to double** to tablica tablic, to trzeba zwolnić kolejno najpierw każdy „wiersz” a potem całą tablicę.
Ale przypisanie nullptr wtedy wystarczy jedno, dla całości.

1 użytkowników online, w tym zalogowanych: 0, gości: 1