dlaczego nie działa kod poniżej:
class ctest
{
public:
const int a,b;
int tab[a][b];
ctest(int a_, int b_):a(a_), b(b_){};
~ctest();
}
oczywiście chodzi o stałe przy deklaracji tablicy, ale dlaczego nie jest to prawidłowe?
dlaczego nie działa kod poniżej:
class ctest
{
public:
const int a,b;
int tab[a][b];
ctest(int a_, int b_):a(a_), b(b_){};
~ctest();
}
oczywiście chodzi o stałe przy deklaracji tablicy, ale dlaczego nie jest to prawidłowe?
dlatego, ze zeby zainicjowac zmienna tablicowa to musi byc jej rozmiar - nie mozesz ustallic sobie rozmiaru tablicy w trakcie dzialania programu. Prosty przyklad zmienna int, zajmuje 2 bajty, zmienna char 1 bajt - a ile zajmuje char a[_c]; ??? Dlatego jest to blad...
no wlasnie zastanawia mnie, po co w takim razie lista inicjatorow, myslalem ze wlasnie po to, aby obiekt w momencie inicjacji mial zdefiniowane konkretne wartosci - w tym wypadku stalych...
Jest sposob by to ominac. Po prostu utworz tablice dynamiczna :
int *tab=new int [a][b];
teraz masz jednak dostep o tablicy przy pomocy wskaznika, a nie kazdy to lubi. Aha i nie zapomnij w destruktorze dodac:
delete tab;
teraz masz jednak dostep o tablicy przy pomocy wskaznika, a nie kazdy to lubi.
Nie rozumiem, a jak moze byc dostep do tablicy nie jako do wskaznika? Przeciez tablica to jest wskaznik. A co do deklarowania wielowymiarowych to ja, preferuje troszke inne rozwiazanie:
tab = new int*[a];
for(int i=0;i<a;i++)
tab[i] = new int[b];
Oczywiscie przy kwadratowych tablicach to nie widac korzysci, ale juz przy trojkatych.. ;)
raybones: inicjalizacja taka ma pare zalet:
Jest sposob by to ominac. Po prostu utworz tablice dynamiczna :
int *tab=new int [a][b];
teraz masz jednak dostep o tablicy przy pomocy wskaznika, a nie kazdy to lubi. Aha i nie zapomnij w destruktorze dodac:
delete tab;
Zaraz zaraz.... a nie powinno byc
delete[][] tab;
?
Bo samym deletem usuwasz tylko pierwszy element, no i mamy ladny wyciek... Jak zle mowie to nie bijcie ;)
pzdrv.
new int[a][b] - to jest przeciez niemozliwe, mozna jedynie new int[a*b]
w rzeczy samej, skorzystam z preferencji Dryobatesa. tak wyglada cala definicja klasy ctest:
class ctest
{
int a,b;
int **tab;
public:
ctest(int aa, int bb)
{
a=aa; b=bb;
//krok 1
tab=new int*[aa];
//krok 2
for (int i=0; i<aa; i++)
{
tab[i]=new int [bb];
};
};
~ctest()
{
for (int i=0; i<a; i++) delete[] tab[i];
};
};
Sposob ktory przedstawil STYX niestety nie dziala (slusznie Ali G).
Pytanie jeszcze, czy wlasciwa jest konstrukcja destruktora?
Czy dobrze rozumuje: operator delete[] zwalnia w tym wypadku pamiec przydzielona w kroku nr 2 dla kazdego elementu tablicy z kroku nr 1?
I dlaczego pojawia sie blad przy wywolaniu delete [][]tab?
Test wykazal ze pamiec wraca po zakonczeniu dzialania programu, ale pamiec jest zwalniana nawet jesli zostawie cialo destruktora puste!
class ctest
{
int a,b;
int **tab;
public:
ctest(int aa, int bb)
{
a=aa; b=bb;
//krok 1
tab=new int*[aa];
//krok 2
for (int i=0; i<aa; i++)
{
tab[i]=new int [bb];
};
};
~ctest()
{
for (int i=0; i<a; i++) delete[] tab[i];
};
};
ta klasa jest prawidlowa ale destructor powinien wygladac troszke inaczej:
~ctest()
{
for(int i=0;i<a;i++) delete [] tab[i];
delete [] tab; //<- i tu sie zwalnia pamiec z kroku pierwszego...
}
<quote>I dlaczego pojawia sie blad przy wywolaniu delete [][]tab?</quote>
poniewaz delete [] cos_tam oznacza usuniecie calej tablicy wskaznikow... a nie mozna uzyc delete [][] cos_tam; bo kompilator nie wie co dokladnie z tym zrobic, poniewaz akceptuje tylko jednowymiarowa tablice wzkaznikow i nie wie czy w tej tablicy sa kolejne tablice czy moze tez obiekty... dlatego sie pruje... po prostu nie da sie usunac dwu i wiecej wymiarowych tablic w ten sposob...
Test wykazal ze pamiec wraca po zakonczeniu dzialania programu, ale pamiec jest zwalniana nawet jesli zostawie cialo destruktora puste!
a to zalezy od tego jakiego kompilatora uzywasz... bo to jest tak ze jesli uruchamiasz program z pod kompilatora to on sam usunie wszystko z pamieci co nie zostalo usuniete przez Ciebie w destruktorze... jesli jednak odpalisz program poza nim to sie moze okazac ze jakies smieci zostaną... C++ to niestety nie Java gdzie sie w ogóle nie pisze destruktorow bo sa nie potrzebne :-P
pozdrawiam
JAK WSTAWIC CYTAT
A JUŻ WIEM
Dzieki cool_szczur :) Dobrze przeczuwalem ze ten destruktor to tak nie do konca byl napisany :) A z tym delete[][] to moze to byc zwykly blad skladniowy, pewnie jest tylko delete []. Dzieki bardzo, to rozwialo moje watpliwosci!
Pozdrowionka [cya]
No a j sie przyznaje, rzeczywiscie sie walnalem przy pisaniu tego,pewnie dlatego ze nie sprawdzilem tego na kompie tylko od razu napisalem co mi do glowy przyszlo, roki za zamieszanie :]
Spoko, zdarza sie [cygaro]