PDA

Tam Sürümünü Görmek İçin : destructor dışında bir yerde pointer silmek için


ankakusu
15/08/2007, 15:22
Merhaba,

Ben simdi de merge sort algoritması yazmaya calisiyordum. Bir tane MergeSort diye bir class yarattım. Altta yazdim kodlari;
dosyalara ayri ayri bakmak daha kolay gelecekse
ekte de yolladım.

Burada burada MergeSort classından bir m1 dosyası yaratırken
bir sorun yaşıyor. Şimdi 2 adet constructor var.
1) Bir tanesi:

MergeSort()

2) ikincisi de

MergeSort(int * const array,int uzunluk)

şimdi bu ikinci constructorun içinde ben bi tane
temp diye bir pointer yarattım işte bu pointer ile
parametre olarak aldığım array içindeki verileri m1
objesine veri olarak giriyorum. Şimdi m1 objesinin
kendi pointerı olan dizi_isaret'i kullanmak istemedim
cunku bu pointer'ın degerinin degismemesi gerekli ki
herhangi bir zaman cagirmak istediğimde doğru yeri
isaret eden bir pointer'ım olsun.

İste heap'i de bosu bosuna harcamayayim diye de
constructor'un sonun da bu temp pointerını sileyim
dedim ama tam bu kısımda bir sorun yaşıyor program.

Destructor dışında bir yerde pointer silmek yassah mıdır?

o yüzden mi?

Başka bir çözüm geldi şimdi aklıma acaba dizi_isaret 'i
dizideki verileri atarken constructor'un sonunda da yine
olması gereken değere set etsem güzel olur mu dersin?

MergeSort.h
class MergeSort
{
public:
int* merge_sort(int * const array,int first, int last);
void uzunluk_ne(int * u);
void dizi_iste(int *ptr);

MergeSort (int * const array , int u);
MergeSort();
virtual ~MergeSort();

private:
int uzunluk;
int dizi[1];
int *dizi_isaret;
};


MergeSort.cpp

MergeSort::MergeSort()
{
dizi_isaret = new int;
uzunluk = 0;
dizi [uzunluk] = 0;
dizi_isaret = dizi;
}

MergeSort::~MergeSort()
{

}

MergeSort::MergeSort(int * const array ,int u)
{
int *temp = new int;
int *dizi_isaret= new int;
uzunluk = u;
dizi_isaret = array;
temp = array;

dizi[uzunluk];

for (int i=0;i<u;i++)
{
dizi[i] = *temp;
temp++;
}
delete temp;
}

void MergeSort::dizi_iste(int *ptr)
{
ptr = dizi;
}

void MergeSort::uzunluk_ne(int *u)
{
*u = uzunluk;
}

int* MergeSort::merge_sort(int * const array, int first, int last)
{
int middle;
int *LeftHalfArray,*RightHalfArray;

if ( (first-last+1) == 1) return array;
else
{
middle = (int) ((last+first)/2);
LeftHalfArray = merge_sort(array,first,middle);
RightHalfArray = merge_sort(array,middle+1,last);
}
return array;
}


main.cpp


int main(int argc, char* argv[])
{
int array[] = { 2,6,1,9,0,4};
MergeSort m1(array , 6);
//m1.merge_sort(array,0,5);

return 0;
}


acehreli
15/08/2007, 22:32
dizi_isaret'i hicbir int'i gostermeden de tanimlayabilirsin. En iyisi 0'a (NULL'a) esitlemektir:

dizi_isaret = 0;

Cunku sen dizi_isaret'in yeni olusturulmus bir int'i degil, dizi'yi gostermesini istiyorsun.

Ali

golgepapaz
15/08/2007, 22:50
Merhaba,

Ben simdi de merge sort algoritması yazmaya calisiyordum. Bir tane MergeSort diye bir class yarattım. Altta yazdim kodlari;
dosyalara ayri ayri bakmak daha kolay gelecekse
ekte de yolladım.
Cok hos cok guzel. kodu gondermen iyi olmus.

Burada burada MergeSort classından bir m1 dosyası yaratırken
bir sorun yaşıyor. Şimdi 2 adet constructor var.
1) Bir tanesi:

MergeSort()

2) ikincisi de

MergeSort(int * const array,int uzunluk)
pekala


şimdi bu ikinci constructorun içinde ben bi tane
temp diye bir pointer yarattım işte bu pointer ile
parametre olarak aldığım array içindeki verileri m1
objesine veri olarak giriyorum. Şimdi m1 objesinin
kendi pointerı olan dizi_isaret'i kullanmak istemedim
cunku bu pointer'ın degerinin degismemesi gerekli ki
herhangi bir zaman cagirmak istediğimde doğru yeri
isaret eden bir pointer'ım olsun.

İste heap'i de bosu bosuna harcamayayim diye de
constructor'un sonun da bu temp pointerını sileyim
dedim ama tam bu kısımda bir sorun yaşıyor program.

Destructor dışında bir yerde pointer silmek yassah mıdır?

o yüzden mi?

Başka bir çözüm geldi şimdi aklıma acaba dizi_isaret 'i
dizideki verileri atarken constructor'un sonunda da yine
olması gereken değere set etsem güzel olur mu dersin?yassah mi degil mi bilemem ama yasak degil. ama senin sorunun bundan daha buyuk.
.Isaretcilerle ilgili yerine oturtman gerken bayagi bir sey var. Yazdigin kodun iler tutar yani olmadigi icin sadece senin su constructor'u bi inceleyelim. ordan kapacagin seylerle kodun gerisini duzeltmek sana kalmis...




MergeSort::MergeSort(int * const array ,int u)
// okey.anladigim kadariyla bu ctr'nin amaci gecilen bir arrayin kopyasini
// alip daha sonra sort etmek, arrayler fonksiyonlara gecerken pointer'e
// decay olurlar(eger referans gecmiyorsan) ayni ctr
// MergeSort(int array[], int u) seklindede yazilabilirdi gerci, boylece asil niyetin
// ne oldugunu anlamis olurduk...
{
int *temp = new int;
// oncelikle bir pointer deklare etmek icin free store'dan(heap C icin kullanilir c++
// da free store diyoruz) yer alman gerekmiyor, yani int* temp; demen yeterli.
// Eger oraya bir sey koymayacaksan yer alman da gerekmiyor,ayrica temp'i ne icin
//kullanacaksin acaba gercekten gerek var mi?


int *dizi_isaret= new int;
// yukaridakinin aynisi
uzunluk = u;

dizi_isaret = array;
temp = array;
// evet bu tumceleri yazdigin anda hafizada(free store) iki int sizma yapti(memory
// leak) ,artik sen her MergeSort yarattiginda hafizada yeni sizmalar olacak. ayrica
// bunu yapmandaki amac ne ? array'i temp e kopyalamaya calismadigina gore (onu
// asagida yapmissin), array'in kendisini kullanman daha dogru degil mi??

dizi[uzunluk];

// ah bu cok iyi iste.sanirim dizi'nin boyunu array'in boyuyla esitlemeye calismissin
// ama yukaridaki tumce hic birsey yapmaz, sadece dizi arrayinin uzunluk indeksindeki //veriyi dondurur.ki sen diziyi bir 1 lik bir array olarak tanimladigin icin de bu sacma
// sapa nbir deger olacaktir. eger dizini boyunun calisma zamaninda(runtime)
// degisatirmek istiyorsan diziyi bir pointer olarak tanimlayip, dinamik olarak hafizadan
// yer alamn gerekiyor
// yani soyle bisey;
// int dizi*; //headerin icinde
// dizi = new int[uzunluk]; //constructorun icinde


for (int i=0;i<u;i++)
{
dizi = *temp;
temp++;
}
[I]// program belki az once cakmadi ama su anda cakti. i nin degeri 1 oldugu an
// dizi[1]=*temp cakicaktir,cunku sana ait olmayan bir hafiza bolgesine yada
//programdaki baska bir seyin uzerine yazdin. her durumda programin hatali durumda
// su an
// eger bir onceki tavsiyeyi uygular ve dizi icin array'i=temp'i=dizi_isaret'i tutabilecek
// kadar yer ayirirsan yukaridaki kod duzgun olarak calisir.


delete temp;
// bu sefer kesin cakti, cunku arrayi silmeye calistin (hatirlarsan temp=array yapmistin)
// ilk once bir seyi delete edebilmen icin onun free store(heap degil ok?)da yaratilmasi
// ama main'e baktigimizda array'in stackte yaratildigini goruyoruz.. ikinci olarak array
// free store da yaratilsa bile, eger array'in sahibi sort etmesi icin verdigi arrayin
// silindigini gorunce okkali bir kufur savurur heralde... :)
}


okay simdi de bakalim main 'de neler duzeltebiliriz onu gorelim....

int main(int argc, char* argv[])
// eger argc ve argv yi kullanmiyorsan yazmana gerek yok....
// int main() ayni isi gorecektir.
{
int array[] = { 2,6,1,9,0,4};
MergeSort m1(array , 6);
m1.merge_sort(array,0,5);
// okay merge_sort u incelemedim ama m1 i yaratirken arrayi
// zaten kopyaladigimiz icin bir daha gecmenin anlami yok
// soyle bir sey daha uygun olacaktir.
// int * sorted_array=m1.merge_sort();

return 0;
// bunu silebilirsin main den birsey donmek zorunda degilsin
}

simdi bu bu constructor'u ve main'i bir daha yazalim


MergeSort::MergeSort(int array[], int u):uzunluk(u)
{
dizi = new int[uzunluk];
for (int i=0;i<u;++i)
{
dizi[i] = *array++;
}
}
MergeSort::~MergeSort()
{
delete[] dizi; // destructor ta silmek yine de iyi bir fikir....
}

int main()
{
int array[] = { 2,6,1,9,0,4};
MergeSort m1(array , 6);
int *sorted_array=m1.merge_sort();
}


Nasil cok daha temiz oldu dimi?

ankakusu
15/08/2007, 22:54
aslında benim merak ettiğim şuydu:

MergeSort(int * const array ,int u)
constructor'unun içinde delete temp diye
bir ifade var en sonda. işte o ifade olduğu
zaman run time error veriyor.

ama o ifadeyi kaldırdığım zaman ise
bir sorun yok...

yani çalışıyor.

Neden böyle bir sorun yaşanır ki?

bir pointer silmek bu kadar mı zor bir şey?

golgepapaz
15/08/2007, 23:18
aslında benim merak ettiğim şuydu:

MergeSort(int * const array ,int u)
constructor'unun içinde delete temp diye
bir ifade var en sonda. işte o ifade olduğu
zaman run time error veriyor.

ama o ifadeyi kaldırdığım zaman ise
bir sorun yok...

yani çalışıyor.

Neden böyle bir sorun yaşanır ki?

bir pointer silmek bu kadar mı zor bir şey?

ee yazdim ya


delete temp;
// bu sefer kesin cakti, cunku arrayi silmeye calistin (hatirlarsan temp=array yapmistin)
// ilk once bir seyi delete edebilmen icin onun free store(heap degil ok?)da yaratilmasi
// ama main'e baktigimizda array'in stackte yaratildigini goruyoruz.. ikinci olarak array
// free store da yaratilsa bile, eger array'in sahibi sort etmesi icin verdigi arrayin
// silindigini gorunce okkali bir kufur savurur heralde... :)

ankakusu
16/08/2007, 00:25
Merhaba GolgePapaz oncelikle yardim icin tesekkur ederim.

MergeSort::MergeSort(int * const array ,int u
// okey.anladigim kadariyla bu ctr'nin amaci gecilen bir arrayin kopyasini
// alip daha sonra sort etmek, arrayler fonksiyonlara gecerken pointer'e
// decay olurlar(eger referans gecmiyorsan) ayni ctr
// MergeSort(int array[], int u) seklindede yazilabilirdi gerci, boylece asil niyetin
// ne oldugunu anlamis olurduk...

evet dediğin gibi kullanıcının dizisiniz alıp kopyalayacağım.
evet direk array olarak da alabilirdim.

ama ben de pointerlar konusunda bazi eksiklerimin olduğunun
farkında olduğum için pointer olarak aldım. Hatları çözerken
öğrenirim diye...
Ayrıca int *const array ile int array[] yakın şeylerdir.
sonuç olarak array dediğimiz de baş kısmı sabit olan bir pointer değil midir?
yani constant integer pointer (=int * const )

benim burada girdi olarak aldığım array'in adresidir ve ben de bu pointer'ı alarak
aslında array'in kendisini almakla aynı şeyi yapıyorum.
MergeSort(int * const array ,int u)

{
int *temp = new int;
// oncelikle bir pointer deklare etmek icin free store'dan(heap C icin kullanilir c++
// da free store diyoruz) yer alman gerekmiyor, yani int* temp; demen yeterli.
// Eger oraya bir sey koymayacaksan yer alman da gerekmiyor,ayrica temp'i ne icin
//kullanacaksin acaba gercekten gerek var mi?
valla new int olarak yaratmazsam run time error veriyordu. O yuzden boyle
yapmistim. Belki bu benim compiler'dan kaynaklanan bir sorun olabilir.


dizi_isaret = array;
temp = array;
// evet bu tumceleri yazdigin anda hafizada(free store) iki int sizma yapti(memory
// leak) ,artik sen her MergeSort yarattiginda hafizada yeni sizmalar olacak. ayrica
// bunu yapmandaki amac ne ? array'i temp e kopyalamaya calismadigina gore (onu
// asagida yapmissin), array'in kendisini kullanman daha dogru degil mi??


şimdi girdiyi bir pointer olarak aldım ve bu sabit olan ve int'i işaret eden bir pointer.
bu pointer'ın değerini değiştiremem çünkü sabit. O yuzden bir de dizi_isaret'de yarattim. girilen dizinin adresini tutmak icin. ama benim dizi_isaret'i de degistirmemem
gerekiyor. cunku dizinin adresini kaybetmemem gerekli. Bu yuzden bir de temp diye bir pointer yarattım. Bu pointer'ı dilediğim gibi degistirebilirim...


dizi[uzunluk];

// ah bu cok iyi iste.sanirim dizi'nin boyunu array'in boyuyla esitlemeye calismissin
// ama yukaridaki tumce hic birsey yapmaz, sadece dizi arrayinin uzunluk indeksindeki //veriyi dondurur.ki sen diziyi bir 1 lik bir array olarak tanimladigin icin de bu sacma
// sapa nbir deger olacaktir. eger dizini boyunun calisma zamaninda(runtime)
// degisatirmek istiyorsan diziyi bir pointer olarak tanimlayip, dinamik olarak hafizadan
// yer alamn gerekiyor
// yani soyle bisey;
// int dizi*; //headerin icinde
// dizi = new int[uzunluk]; //constructorun icinde

evet ilk başta dizinin uzunluğunu 1 olarak yaratmak durumunda kaldım çünkü derleyici uyarı veriyordu. ben de bari bir ilk değer atayayım daha sonradan değiştirebilirim diye
düşündüm... Ama tabii yazdığımın doğru olup olmadığından emin değildim doğrusunu söylemek gerekirse.

şu run time değişiklik için verdiğim fikir için sağol. sanırım bu yol daha iyi bir yol olacak.


for (int i=0;i<u;i++)
{
dizi = *temp;
temp++;
}
[I]// program belki az once cakmadi ama su anda cakti. i nin degeri 1 oldugu an
// dizi[1]=*temp cakicaktir,cunku sana ait olmayan bir hafiza bolgesine yada
//programdaki baska bir seyin uzerine yazdin. her durumda programin hatali durumda
// su an
// eger bir onceki tavsiyeyi uygular ve dizi icin array'i=temp'i=dizi_isaret'i tutabilecek
// kadar yer ayirirsan yukaridaki kod duzgun olarak calisir.

evet bunu uygulamaya çalışacağım.
delete temp;
// bu sefer kesin cakti, cunku arrayi silmeye calistin (hatirlarsan temp=array yapmistin)
// ilk once bir seyi delete edebilmen icin onun free store(heap degil ok?)da yaratilmasi
// ama main'e baktigimizda array'in stackte yaratildigini goruyoruz.. ikinci olarak array
// free store da yaratilsa bile, eger array'in sahibi sort etmesi icin verdigi arrayin
// silindigini gorunce okkali bir kufur savurur heralde... :)
}

bak burasını anlamadım işte. Ben array'i filan silmiyorum ki? Ben array'i pointer'a eşitledim pointer'ı array'e değil ki! sen demek istiyorsun ki ben temp = array yaptığım zaman bunlar yapışık ikiz gibi bir şey oluyor. Birini silince diğeri de gidiyor. Ama ben şöyle düşünmüştüm ben temp = array dediğim zaman aynı adresi gösteren iki ayrı pointerım olur. biri temp diğeri de array. array'in adresini temp'e de verdim. Yani bir nevi aynı evin iki tane anahtarını çıkartmak ve güvendiğim bir arkadaşıma vermek gibi bir şey bu. Ama ben anahtarı o arkadaşa verdim diye o arkadaşın bizim evde oturmuş olması gerekmiyor ki. Bunların mantığı böyle değildi diye biliyordum ben aslında... :garip:


okay simdi de bakalim main 'de neler duzeltebiliriz onu gorelim....

int main(int argc, char* argv[])
// eger argc ve argv yi kullanmiyorsan yazmana gerek yok....
// int main() ayni isi gorecektir.
{
int array[] = { 2,6,1,9,0,4};
MergeSort m1(array , 6);
m1.merge_sort(array,0,5);
// okay merge_sort u incelemedim ama m1 i yaratirken arrayi
// zaten kopyaladigimiz icin bir daha gecmenin anlami yok
// soyle bir sey daha uygun olacaktir.
// int * sorted_array=m1.merge_sort();

return 0;
// bunu silebilirsin main den birsey donmek zorunda degilsin
}

main rutini direk visual cpp yaratıyor ben de pek ellemek istemiyorum
çünkü abuk sabuk hatalar çıkıyor.