PDA

Tam Sürümünü Görmek İçin : memset( )


ceeyt
20/05/2004, 18:38
herkese selamlar...

asagidaki gibi bir kod icin memset() kullanmaya gerek var midir?

struct boolVars{
bool b1;
bool b2;
};

class Vars {
boolVars bv;
/*
.............
*/
};

int main()
{
/*
..........
*/
return 0;
}

boolVars degiskenlerini ilk kullanima Vars() yapilandiricisiyla hazirlamak yeterli olmaz mi, memset() in bir avantaji var midir ?

tesekkur ederim.


acehreli
21/05/2004, 00:27
Ben kisa bir sure once bir tartismaya katilmis ve o zamana kadar iki kavrami birbirine karistirdigimi ogrenmistim: ilkdegerleme (initialization) ve yapilandirma (construction (ben buna cogunlukla 'kurma' diyorum)).

O Ingilizce tartismayi izleyerek benim ogrendiklerimi ogrenmek isterseniz groups.google.com'da cift tirnaklar da dahil olmak uzere su aramayi yaptirin: "Is `new classname' the same as `new classname()' ?"

Simdi soruya donebilirim... :)

memset'e gerek yoktur cunku C++ POD turleri icin ilkdegerlemenin nasil yapildigini tanimlamistir. Ancak, ilkdegerlemeyi acikca bizim istememiz gerekir.

Bilmeyenler icin, POD 'plain old data' (siradan veri/bayagi veri) anlamina geliyor. Hangi turlerin POD sayildiklarini tam hatirlayamiyorum ama sorudaki boolVars gibi yapilarin oyle olduklarini biliyorum.

POD turlerinden nesneleri ilkdegerlendirmek icin, onlari kuran yerde yanlarina bir cift bos parantez koymak yeterli oluyor. Bu durumda 'bv'yi kuran ortam Vars'in yapilandiricisi oldugu icin, 'bv'nin ilkdegerlendirilmesini soyle istememiz gerekiyor:


Vars()
:
bv()
{}


Bu durumda 'bv'nin her iki ogesinin degeri 'false' olacaktir. Eger oyle yapmaz da yapilandiriciyi asagidaki gibi yazarsak, 'bv'nin ogelerinin degerleri belirsiz kalir:


Vars()
{}

Tabii amacimiza boolVars'a bir kurucu islev ekleyerek de erisebiliriz. Bu, ozellikle ogelerden bazilarinin 0'dan (veya 'false'dan) baska bir ilk deger almasinin gerektigi durumlarda gerekir:


struct boolVars
{
boolVars()
:
b1(false),
b2(true)
{}
/* ... */
};


'bv'nin gercekten ilkdegerlendigini asagidaki program yardimiyla gorebilirsiniz. Vars() kurucusu 'bv'yi acikca ilkdegerledigi icin, 'bv'nin ogelerinin sifirlandiklarini goreceksiniz. Eger Vars() kurucusunu siler veya yukaridaki gibi 'Vars(){}' olarak tanimlarsaniz b1 ve b2'nin sifirlanmadiklarini goreceksiniz.

Programda amacima ulasmak icin 'yerlestirme new'u kullandim. Umarim ortaligi fazla karistirmamisimdir. :)

Ali


#include <iostream>
#include <stdlib.h>

struct boolVars
{
bool b1;
bool b2;
};

class Vars
{
public:

/*
'bv'yi deneme programi oldugu icin 'public'
yapiyorum. Yoksa genelde hicbir oge genel
erisime acik olmamalidir.
*/

boolVars bv;

Vars()
:
bv()
{}
};

int main()
{
/*
Vars turunden bir nesneyi kurmak icin
bellek ayiriyorum.
*/
char * bellek = (char *)malloc(sizeof(Vars));

/*
O bellegi sifirdan baska degerlerle dolduruyorum
*/
for (int i = 0; i != sizeof(Vars); ++i)
{
bellek[i] = i + 111;
}

/*
Nesneyi, o bellek alaninda 'yerlestirme new'u
ile kuruyorum.

Yerlestirme new'nun normal new'den farki, ayrica
bellek ayirmamasi ve nesneyi kendisine gosterilen
bellekte kurmasidir.
*/
Vars * nesne = new (bellek) Vars;

std::cout << nesne->bv.b1 << ' '
<< nesne->bv.b2 << '\n';

/*
Yerlestirme new'u kullanmissam nesneyi
acikca sonlandirmam gerekir:
*/
nesne->~Vars();

// Ve sonunda bellegi geri veriyorum
free(bellek);

return 0;
}

acehreli
21/05/2004, 00:59
Bu konu benim icin hAlA cok karisik. Yukaridaki programda 'nesne'yi kurarken soyle yazmistim:

Vars * nesne = new (bellek) Vars;

Peki ya soyle yazsaydim?

Vars * nesne = new (bellek) Vars();

Butun durumlara bir cizelge halinde bakmak istiyorum.

Iki tane kurma yonteminden bahsetmis olduk:

k1: Vars * nesne = new (bellek) Vars;

k2: Vars * nesne = new (bellek) Vars();

Vars kurucusu icin de uc secenege bakmak istiyorum:

v1: Kurucuyu 'Vars():bv(){}' olarak tanimlasak; Bu durumda 'bv'nin ilkdegerlenmesini acikca istemis oluyoruz.

v2: Kurucuyu 'Vars(){}' olarak tanimlasak; Bu durumda 'bv'nin ilkdegerlenMEmesini istemis oluyoruz

v3: Hic Vars kurucusu yazmasak; Bu durumda Vars kendisi bir POD turu olmaya baslar! Vars kendisi yalnizca temel turlerden veya POD turlerden olustugu icin, kendisi de POD'dir. Onun icin POD'lerle ilgili olan ilkdegerlenme kurallari onun icin de gecerlidir. (Asagidaki v3+k2 durumu.)

Butun durumlar icin programin ciktisina bakalim (Butun bunlari gcc 3.2 ile deniyorum):

v1+k1: 0 0

v1+k2: 0 0

v2+k1: 111 112

v2+k2: 111 112

v3+k1: 111 112

v3+k2: 0 0

Yani 'bv'nin ilkdegerlenmesini istiyorsak, bunu 'Vars():bv(){}' seklinde acikca istemeliyiz. En sondaki durum ise Vars'in kendisinin POD oldugu duruma karsilik geliyor. Bu benim biraz olsun kafami karistirdi. :)

Vars'in POD olmamasini saglamak icin ona POD olmayan herhangi bir tur eklemek yeterli olur. Ornegin bir std::string oge ekledigimiz anda yeni cikti beklendigi gibi soyle oluyor:

v3+k2: 111 112

Ali

ceeyt
21/05/2004, 02:00
cevabiniz icin teskkur ederim,

Vars::Vars()
{
bv.b1=true;
bv.b2=false;
}

bu sekilde kullanmamin bir sakincasi yoktur sanirim,cunku boolVals i baska siniflar baska
ilk degerlerle kullaniyorlar.

acehreli
21/05/2004, 02:49
O zaman en iyisi boolVars'a kendi kurucu islevini vermektir. Tamamen bir veri yapisi oldugu icin butun ogelerini hAlA public yapmak isteyebilirsin. class yerine struct tanimlayarak bu niyeti acik etmis olabilirsin.

Yine de hic olmazsa kurulumunu tek bir noktaya tasimak icin soyle bir kurucu islev tanimlamak istiyorsun (inan bana :) ):


struct boolVars
{
bool b1;
bool b2;

boolVars(bool b1_, bool b2_)
:
b1(b1_),
b2(b2_)
{}
};


Boylece kullanici kodlari ornegin soyle olabilir:



class Vars
{
boolVars bv;

/* ... */

Vars()
:
bv(false, true)
{}
};


Dedigin gibi, baska kullanicilar baska degerlerle de kullanabilirler:


boolVars b(true, true);


Ali

ceeyt
21/05/2004, 03:03
dogru cok mantikli.Aslinda boyle birseye ihtiyacim oldugu belliydi,neden ilk yaptigima basvurdum bilmiyorum.Bazen uzun yol daha mi cazip gorunuyor acaba ?
siz nasil anladiniz onu bilmiyorum iste :)

Bir sey daha sormak istiyorum,ben dinamik belek islemlerini sadece ilgili sinif elemanlari icin bellek ayirarak yapiyorum.Cok karmasik bir islem yani ,genellikle yapılandırıcıda bellek ayir,yok edicide ayrilan bellegi sil :)

sizin orneginizdeki gibi tum sinif icin bellek ayirmada,bazi problemlerimin olmasindan korkuyorum oda su;

benim ozellikle bir sinifimda, GPRS modemle gonderilecek 'frame' leri tutan bir vektor var.Sistemde 5 cesit 'frame' tanimli ve boyutlari 20 bytes ve 1028 bytes arasinda degisiyor.
Ben bellek ayirma isini vektorun en buyuk boyutuna gore yaparsam bosu bosuna bellegi mesgul ederim,kucuk olana gore yaparsam bu sefer performans sorunlari olabilir.Acaba bu iş icin bir gauss olasilik-yogunluk fonksiyonu tanimlasam ona giris olarak random number generatorden gelen sayiya gore bana ayrimam gereken mktari gosterse isime yarayabilir diye dusunuyorm,mutlaka daha basit bir yolu vardir.az once yukarida kanitladiginiz gibi :)

acehreli
25/05/2004, 21:20
Bence bu tur bir sorunda dinamik bellek kullanmak daha akilli olacak gibi gorunuyor. Ancak, o dinamik bellekle kimin ugrasacagindan emin degilim. string, vector, vs. gibi topluluklar kullanirsan, gerektigi kadar buyuyen ama kendi belleklerini kendileri yoneten nesnelerin olmus olacak.

Yani dinamik bellek gerekecektir ama o bellekleri kendin ayirip geri vermekten kacinmalisin.

Kendin ayirdiginda da o bellegi mutlaka bir akilli gostergeye emanet etmeni oneririm.