Tam Sürümünü Görmek İçin : vektörlerde pointer kullanımı sorusu
Darkstar
26/11/2004, 08:10
void afunction()
{
vector<Myclass *> v;
v.push_back(new Myclass);
v.push_back(new Myclass);
v.push_back(new Myclass);
.......
v.clear(); //burada v.clear() yeterli midir? yoksa tek tek tüm allocate
//edilen objeleri simemiz gereklimidir?
return;
}
Silme derken, bellekte ayrilan alani silme mi,yoksa degerini silme mi kast ediliyor? Bellegin geri verilmesi ise tek deallocate ile silinmez,degerlerin silinmesi ise silinir.
v.clear(), v.erase( v.begin( ), v.end( ) ); ile ayni isi yapar,yani sadece elemanlari siler.
Bu konu asagidaki forum konusunda da tartisilmisti.
http://forum.ceviz.net/showthread.php?t=14446
#include <vector>
#include <iostream>
using namespace std;
class Myclass {
public:
int i;
Myclass():i(2){}
};
void afunction(void);
int main()
{
afunction();
return 0;
}
void afunction()
{
vector<Myclass *> v;
v.push_back(new Myclass);
cout <<'s' << v.size() <<endl;
cout <<'c' << v.capacity() <<endl;
v.push_back(new Myclass);
cout <<'s' << v.size() <<endl;
v.push_back(new Myclass);
cout <<'s' << v.size() <<endl;
v.clear();
cout <<'s' << v.size() <<endl;
cout <<'c' << v.capacity() <<endl;
return;
}
Gordugun gibi clear() kapasiteyi etkilemiyor.
Sorunun cevabi; her eleman icin delete yazmalisin.
hatta daha dallandırıp,budaklandıralım :)
class Myclass {
public:
int *i;
Myclass() { i = new int; }
~Myclass() { delete i; }
};
Myclass boyle yazilmissa ne olacak ?
delete Myclass; ayni zamanda Myclass in bozucu islevini cagirir. Buna göre Myclass iki sekilde de tanimlansa ; v icindeki her elaman icin delete yazarak bellekte ayrilan alani silebiliriz,daha dogrusu geri verebiliriz.
sunu da ekleyeyim ;
class Myclass {
public:
int *i;
Myclass() { i = new int;}
}
Myclass bu sekilde yazilmissa,yani i icin ayrilan bellek bozucu islevde geri verilmiyorsa, sadece vektorun elemanlarini delete etmen yeterli olmaz
mesela v nin ilk elemaninin tuttugu bellegi delete v[0] ; ile geri vermek istersen ;
1- delete ifadesi,vektorun ilgili elemani icin ayrilmis bellegi geri verir .
2- yine delete, bu eleman icin derleyici tarafindan olusturulmus bozucu islevi cagirir.Cagrilan bozucu islevde, delete i; ifadesi olmadigindan, i icin ayrilan alan geri verilememis olur.
Bundan dolayi once,vektorun ilgili elemanindaki i icin ayrilmis belelk geri verilmeli,ondan sonra elemanin kendisi icin ayrilan yer geri verilmelidir.
itr adinda bu vektore erisen bir erisicimiz olsun;
once delete itr->i; ardindan delete v[0]; gibi kullanman gerekir.
Sorduklarinin hepsi ve son verdigim Myclass ornekleri ile ayni mantikta durumlar icin forumda yazismalar olmustu,onlara da bakarsan daha cok fikir sahibi olursun.
acehreli
26/11/2004, 20:23
Darkstar, aslinda clear islemi gercekten de vector icindeki butun nesneleri sonlandirir. Sonlanan nesnelerin ne olduklarini dusunmek gerekir. Bu durumda vector'un nesneleri gosterge olduklarindan, gostergelerin kendileri sonlanirlar. Onlarin gosterdikleri nesnelere bir sey olmaz.
vector'un bulunmadigi soyle bir durumda da oldugu gibi:
{
int * p = new int(42);
} // Bu noktada p sonlanir ama 'delete p;' ifadesi isletilmez
Zaten vector gostergelerin gosterdikleri nesnelerin nereden nasil alindiklarini ve onlari kendisinin sonlandirip sonlandirmayacagindan emin olamaz:
int * p = new int(42);
vector<int*> v;
v.push_back(p);
v.clear(); // burada vector'un p'nin gosterdigi nesneyi
// sonlandirmaya hakki yoktur...
*p = 7; // ... cunku burada hAlA kullaniyoruz
delete p;
Hatta, vector o gostergelerin yigittaki nesneleri mi veya ornegin malloc ile ayrilan bir bellekte oturan nesneleri mi gosterdiklerini de bilemez. O yuzden onlari "delete edemez."
vector bu isi yapamayacagina gore, bu is bizim tarafimizdan ve uygun bir kapsamda yapilmalidir. ceeyt'in de soyledigi gibi, her birisi icin acikca bir 'delete' gerekir. O delete'lerin nerede kullanilacaklarini da ancak biz bilebiliriz. En son verdigim kod parcasinda oldugu gibi...
Eger vector sonlanirken icindeki gostergelerin gosterdikleri nesnelerin de sonlanmalarini istiyorsak, o zaman vector<int*> degil, vector<AkilliGosterge<int*> > kullanmamiz gerekir. Cunku bu durumda vector'un icindeki nesnelerin turu AkilliGosterge<int*> olur ve o nesneler kendileri vector tarafindan sonlandirilirken sorumlusu olduklari nesneleri de sonlandirirlar.
Bu kullanim icin en uygun akilli gosterge, boost::shared_ptr'dir. (Boost kutuphanesini boost.org'dan indirebilirsiniz.) Sunun gibi:
typedef boost::shared_ptr<Myclass> MyclassGostergesi;
typedef vector<MyclassGostergesi> MyclassToplulugu;
MyclassToplulugu nesnelerim;
nesnelerim.push_back(MyclassGostergesi(new Myclass));
nesnelerim.clear();
Artik bellek kaybedilmemis olur.
Genel olarak akilli gostergeleri anlattigim ve Boost akilli gostergelerini tanittigim iki yazi sunlar:
http://ceviz.net/index.php?case=article&id=263&f=34&ff=28
http://ceviz.net/index.php?case=article&id=273
ceeyt, capacity()'nin dondurdugu degeri kullanan ornek kodun konuyu acikladigindan emin degilim. Cunku her gosterge icin biz acikca 'delete' desek bile, veya akilli gostergeler kullansak bile kapasite zaten degismez. vector'un gozunde nesneler sonlanmislardir ama vector daha sonradan yeni nesneler gelebilir dusuncesiyle nesne kapasitesini ayni tutmaktadir. Her nesne icin acikca delete yazsak da kapasite zaten degismez.
Ali
Haklisiniz degismez.O an icin 'clear' in degistiremeyecegi bir seyler ararken,sadece nesne silmeyle degismeyecek bir ornek vermisim :)
' Turkiyenin baskenti neresi? ' sorusuna Ankara ve Istanbul cevabi vermek gibi olmus.
ozellikle soruyu soran arkadastan ozur dilerim...
acehreli
27/11/2004, 11:20
ceeyt, ben ozurluk bir sey oldugunu dusunmuyorum. Birlikte ogreniyoruz... Katkin icin tesekkurler.
Bu arada, ben yazi icinde iki yerde AkilliGosterge<int*> demisim. Onlar aslinda AkilliGosterge<int> olacaklar. Duzeltir ozur dileriz ;)
Ali
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.