Üye GİRİŞİ

Son eklenen makale ve haberler

  Programlama » C / C++

Boost Akıllı Göstergeleri

Ceviz.Net Pdf Çıktısı Al
 
Ceviz.Net Doc Çıktısı Al
 

Giriş


Bir önceki yazımda auto_ptr'ın yeterli olmadığı durumlar için boost.org'un akıllı göstergelerini önermiştim. [1] Bu yazıda Boost akıllı göstergelerinin beş tanesini
kısa örneklerle tanıtmaya çalışacağım:

  scoped_ptr
  scoped_array
  shared_ptr
  shared_array
  weak_ptr

Boost'a sonradan eklenmiş olan intrusive_ptr şablonunu, daha aşağıda sıraladığım nedenlerden dolayı bu yazının konusu dışında bırakacağım.


Boost Kütüphanesi

Standart kütüphaneler bir çok nedenden ötürü kısıtlıdırlar; akla gelen her olanak standartta yer alamaz:

- Standardın daha fazla geciktirilmesi istenmediği için belirli bir olanağın kabulü için zaman kalmamış olabilir

- Eksikliği hissedilen iş bazı standart olanaklar yardımıyla zaten yerine getirilebiliyordur

- Olanak; genelin değil, küçük bir azınlığın ihtiyacıdır

- Olanağın dilin desteklendiği her ortamda gerçeklenmesi mümkün değildir

- vs.

Boost kütüphaneleri, çeşitli nedenlerle standart C++ kütüphanesinin kapsamı dışında kalmış olan bir grup sınıf, sınıf şablonu, ve makrolar topluluğudur.

Boost kütüphaneleri tamamen gönüllüler tarafından önerilir, gerçeklenir, denetlenir, ve kullanıma sunulur.

Rassal sayı üretimi, Python diliyle uyum, platformdan bağımsız işletim dizisi (thread)
programcılığı ve düzenli ifadeler gibi çok sayıdaki olanak arasından benim kendi adıma en çok yararlandıklarım; akıllı göstergelerdir.


Boost Başlıkları

Boost kütüphaneleri hemen hemen tamamen başlık kütükleri içinde tanımlanmışlardır. [2] Bu yüzden, kütüphanelerin büyük çoğunluğunu yalnızca başlıklarını edinerek
kullanabilirsiniz. Kullanmaya başlamadan önce, istediğiniz bir yere kopyalamak dışında herhangi bir kurulum işlemi yapmanıza gerek yoktur.

Bütün başlık kütükleri 'boost' dizini altında ve 'hpp' uzantıları ile yer alırlar.


Boost Ad Alanı

Standart kütüphanedeki adların 'std' ad alanı içinde tanımlanmış olmalarına benzer şekilde, Boost kütüphanesindeki adlar da 'boost' ad alanı içinde tanımlanmışlardır.

O yüzden, o olanakları kullanırken ya tam adlarını yazmak, ya da 'using' bildirimleri veya 'using' komutları kullanmak gerekir.

Bu üç yöntemi, kolayca tür dönüştürme amacıyla kullanılan boost::lexical_cast'i kullanarak göstermek istiyorum:

#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>

using namespace std;

/*
  Bu islev lexical_cast'i tam adiyla kullaniyor
 */
void tamsayi(string const & yaziyla)
{
    int sayi = boost::lexical_cast<int>(yaziyla);
    cout << (sayi * 2) << '
';
}

/*
  Bu islev lexical_cast'in tam adini yazmak zorunda
  degil, cunku bir 'using' bildirimi kullaniyor
 */
void kesirliSayi(string const & yaziyla)
{
    /*
      Bu islev icinde 'lexical_cast' goruldugunde
      onun 'boost::lexical_cast' oldugu anlasilsin
      diye...
     */
    using boost::lexical_cast;

    /*
      Burada 'boost::' kullanmak zorunda degiliz...
     */
    double sayi = lexical_cast<double>(yaziyla);   
    cout << (sayi + 0.6) << '
';
}

/*
  Bu noktadan sonraki islevler acikca  'boost::'
  yazmak zorunda degiller cunku bir 'using' komutu
  kullaniliyor...
 */

using namespace boost;

/*
  Bu islev yalnizca 'lexical_cast' yaziyor ve onun
  ne oldugu anlasiliyor.
 */
void karakter(string const & yaziyla)
{
    char k = lexical_cast<char>(yaziyla);
    ++k;
    cout << k << '
';
}   

int main()
{
    tamsayi("123");
    kesirliSayi("4.5");
    karakter("a");
}


Ben yazının geri kalanında 'using' komutu yöntemini kullanacak ve her seferinde 'boost::' yazmaktan kurtulacağım.


Boost akıllı göstergeleri sınıf şablonudurlar

Bu göstergeler, her türle çalışabilsinler diye sınıf şablonu olarak gerçeklenmişlerdir. Hatırlarsanız, sınıf şablonlarını kullanırken şablon parametrelerini açıkça belirtmek gerekir.

Onun için, örneğin 'int' türünden bir nesneden sorumlu olan bir scoped_ptr'ı 'int' türünü açılı parantezler arasında belirterek şöyle tanımlarız:

    scoped_ptr<int> p(/* ... */);


scoped_ptr
----------

'Scope' İngilizce'de kapsam anlamına gelir. C++ dünyasında bir kod bloğu bir kapsamdır.

scoped_ptr, 'new' ile ayrılan bir bellekte yaşayan ve bir kapsamdan çıkıldığında silinmesi gereken nesneler için kullanılır. Asıl işi, kendisine emanet edilen adresi, kendi yaşamı sonlanırken 'delete' işlecine göndermektir.

'delete'in işi de bir bellekte bulunan nesnenin bozucusunu çağırmak ve o belleği geri vermek olduğu için, scope_ptr kullanarak nesne temizliği hatalarını ve bellek sızıntılarını önlemiş oluruz.
Bu "akıllılığının" dışında, sıradan bir gösterge gibi de çalışır. get() öge işlevi yardımıyla yalın gösterge bekleyen işlevlere rahatça gönderilebilir.

scoped_ptr masrafsız ve basit bir sınıf şablonu olarak tasarlanmıştır. Onun için, atama işleci veya kopyalayıcı tanımlamaz.

Öte yandan, iki tane özel öge işlev sunar:

1) T * get() const;

Sorumluluğunda bulunan nesnenin adresini döndürür.

2) void reset(T * p = 0);

Sorumluluğunda bulunan nesneyi silmesi ve yeni bir nesnenin sorumluluğunu üstlenmesi için kullanılır.

Bu bilgileri kullanan bir örnek program şöyle yazılabilir:

#include <iostream>
#include <boost/scoped_ptr.hpp>

using namespace std;
using namespace boost;

// Oylesine bir yapi

struct Yapi
{
    int i;
    double d;
};


// Yapi kullanan oylesine bir islev

void Yapi_yazdir(Yapi const * yapi)
{
    cout << "(" << yapi->i
         << ", " << yapi->d << ')';
}

void Yapi_deneme()
{
    /*
      Bellekte bir Yapi olusturuyor ve onun
      sorumlulugunu bir scoped_ptr'a veriyoruz:
     */
    scoped_ptr<Yapi> gosterge(new Yapi);

    /*
      'gosterge'yi bir yalin gosterge gibi
      kullanabiliriz. Oge erisim isleci olan -> ile:
    */
    gosterge->i = 1;
    gosterge->d = 1.1;

    /*
      Bir Yapi nesnesi adresi bekleyen bir isleve
      gonderebiliriz.

      Nesnenin adresini 'get' oge islevi ile ediniyoruz:
     */
    Yapi_yazdir(gosterge.get());
    cout << '
';

    /*
      Gosterdigi nesneye * isleciyle erisebiliriz.
     
      (Burada nesneyi anlamsizca kendisine atiyoruz;
      ama olsun...)
     */
    *gosterge = *gosterge;

    /*
      O nesneyi birakip yeni bir tanesini tutmasini
      istiyoruz
     */
    gosterge.reset(new Yapi);

    // Simdi rastgele sayilar gorecegiz:
    Yapi_yazdir(gosterge.get());
    cout << '
';

    /*
      Bu islevin tanimlamis oldugu kapsam nasil
      sonlanirsa sonlansin; ornegin islevden

      - sonuna gelindigi icin
      - bir 'return' satiri ile,
      - atilan bir aykiri durum yuzunden

      cikilmasi durumlarinda, 'gosterge'nin tuttugu
      nesne mutlaka silinecektir.

      Bunu, Yapi yapisi icin

      - kurucu,
      - bozucu,
      - atama isleci ve
      - kopyalayici

      tanimlayarak ve onlara girildiginde ekrana
      yazilar yazdirarak gorebilirsiniz.
     */
}

void ikiye_katla(int * p)
{
    *p *= 2;
}

/*
  Bu da 'int' turunu gosteren bir scoped_ptr ornegi
 */
void int_deneme()
{
    scoped_ptr<int> p(new int);
    *p = 1000;
    ikiye_katla(p.get());
    cout << *p << '
';
}

int main()
{
    Yapi_deneme();
    int_deneme();
}


Aslında bu örnekler scoped_ptr'ın kullanımını göstermek için biraz zorlama oldular. Çünkü
örneklerdeki Yapi ve int nesnelerini dinamik bellekten almanın gereği yoktur. Onun yerine otomatik değişken kullanmak daha doğal olacaktır:

  Yapi yapi;

ve

  int sayi;

gibi... Burada çokşekilliliğin gerektiği bir örnek daha uygun olabilirdi. Aşağıdaki örnekte,
hayvanYap işlevinin dinamik bellekten alarak döndürdüğü belleği hemen bir scoped_ptr'a geçirerek o belleğin otomatik olarak geri verilmesini sağlamış oluyoruz.

#include <boost/scoped_ptr.hpp>

using namespace boost;

struct Hayvan
{
    virtual ~Hayvan()
    {}
};

struct Kedi : public Hayvan {};
struct Kopek : public Hayvan {};

Hayvan * hayvanYap()
{
    return new Kedi;
}

int main()
{
    scoped_ptr<Hayvan> hayvan(hayvanYap());
}




acehreli 20.04.2004
Sayfalar: 1 2 3


co.mments  del.icio.us  digg  Furl  NewsVine  Reddit  Spurl  TailRank  Wists   



Rating : 10 üzerinden 7.38
 



Tümünü Göster / Sadece Başlıklar Yorumlar

Doom Pek Anlasılmamıs Galiba!
pek anlasılmamıs ama cok derin bir döküman ! TeşşeküüRler!
 
mehmet Boost
Boost ile Stl arasında karşılaştırma yapılabilirmi?
 
Ali Çehreli Boost çok büyük
Boost kütüphaneleri için "standart kütüphanenin uzantısı" olarak sözedilir. Bazı parçaları zamanla C++ standardına dahil olur.
 




yorum Yorum ekle
İsminiz:
Mailiniz:
Yorum Konu:
Soru: İlkbahardan sonraki mevsim?
Cevap :
Bütün alanları doldurmanız gerekmektedir.

 
XHTML 1.0 CSS 2.1
Ceviz Reklam