SORU
16 Mart 2010, Salı


İyi bir uygulama her zaman akıllı işaretçileri kullanabilir miyim?

Akıllı işaretçiler işaretçiler çiğ olduğundan çok daha rahat buluyorum. Yani o zaman için iyi bir fikirdirher zamanakıllı işaretçileri kullanmak? ( Lütfen Java kökenli olduğumu unutmayın ve bu nedenle çok açık bellek yönetimi bu fikri sevmedim. Çok akıllı işaretçiler ile ciddi performans sorunları olmadığı sürece, onlarla kalmak istiyorum. )

Java arka plan geldiğim Halde, akıllı işaretçiler uygulanması ve oldukça iyi bir DEMİRYOLU kavramları anlıyorum. not: Cevap gönderirken benim tarafımdan verilen bu bilgi alabilir. Statik ayırma hemen hemen her yerde kullanıyorum ve sadece gerekli işaretçiler kullanın. Benim sorum sadece:Her zaman ham işaretçiler yerine akıllı işaretçileri kullanabilir miyim???

CEVAP
16 Mart 2010, Salı


Çeşitli düzenlemeler dikkate alındığında, kapsamlı bir özet faydalı olacağı kanısındayım.

1. Zaman için değil

Akıllı işaretçiler kullanmamalısınız burada iki durum vardır.

Bunlardan birincisi, aslında C sınıf kullanmamalısınız aynı durum. YANİ: eğer istemci için kaynak kodunu teklif yaparsanız değil sınır DLL. Anekdot söyleyeyim.

İkinci çok daha sık olur:akıllı yönetici sahiplik anlamına gelir. Göstericiler, örneğin: onların ömrü yönetimi olmadan, mevcut kaynakları noktada kullanabilirsiniz

void notowner(const std::string& name)
{
  Class* pointer(0);
  if (name == "cat")
    pointer = getCat();
  else if (name == "dog")
    pointer = getDog();

  if (pointer) doSomething(*pointer);
}

Bu örnek sınırlanır. Ama bir işaretçi anlamsal olarak bu geçersiz bir konuma işaret olabilir bir referans (null işaretçi) farklıdır. Bu durumda, nesne yaşam yönetmek için istemediğin için gayet iyi.

2. Akıllı yöneticiler

Akıllı yönetici bir sınıf yazıyoruz sürece, eğer anahtar kelime kullanırsanızdeletebir şeyleri yanlış yapıyorsun.

Görüş tartışmalı bir nokta, ama hatalı kod birçok örnek inceledikten sonra, artık şans almak istemiyorum. Eğer new yazarsanız, yeni ayrılan bellek için akıllı bir yönetici gerekir. Ve sana şimdi ihtiyacım var.

Bir programcı daha az olduğu anlamına gelmez! Tam tersine, çalışmak için kanıtlanmıştır bu kodu yeniden yerine tekerleği yeniden icat ve üzerinde anahtar bir beceridir.

Şimdi asıl zorluk başlar: hangi akıllı yönetici ?

3. Akıllı işaretçiler

Çeşitli özellikleri ile oradan çeşitli akıllı işaretçiler vardır.

Atlama genellikle kaçınmalısınız std::auto_ptr (fotokopi semantik vidalıdır).

  • scoped_ptr: Tepegöz, kopyalanamaz veya silinemez.
  • unique_ptr: Tepegöz, kopyalanamaz, taşınmış olabilir.
  • 9* / weak_ptr*: bazı Tepegöz (referans sayma), kopyalanabilir.

Genellikle, scoped_ptr unique_ptr de kullanmaya çalışın. Eğer ihtiyacınız varsa birkaç sahipleri tasarımını değiştirmeye çalışın. Eğer tasarım değiştirmek ve çok çeşitli sahipleri ihtiyacınız varsa, kırık olmalı başvuruları döngüleri shared_ptr, ama dikkat bir ortasında weak_ptr bir yerde kullanmak.

4. Akıllı kaplar

Birçok akıllı işaretçiler kopyalanacak demek değildir, bu nedenle STL kapları ile bunların kullanımı biraz şaibeli.

shared_ptr ve havai başvurmak yerine, Boost Pointer Container akıllı kaplar kullanın. Onlar kendi ama mağaza işaretçiler klasik STL kapları arayüzü taklit.

5. Çalışırken kendi

Kendi smart yöneticisi roll isteyebilirsiniz durumlar vardır. Sadece bazı özellik cevapsız olmadığını kontrol edin önceden kullanan kütüphanelerde.

Özel durumlar varlığında akıllı bir yöneticisi yazmak oldukça zordur. Sen genellikle bellek (new başarısız olabilir) veya Copy Constructorno throw garanti varsayalım.

Olabilir, kabul edilebilir, biraz, Yoksay std::bad_alloc özel durumu ve yasal yaptırımlar Copy Constructors sayısı yardımcıları umudunu yitirme... sonuçta, o da ne boost::shared_ptr mu için deleter D şablon parametresi.

Ama tavsiye etmem, özellikle de yeni başlayanlar için. Zor bir mesele, ve hatalar hemen fark olası değil.

6. Örnekler

// For the sake of short code, avoid in real code ;)
using namespace boost;

// Example classes
//   Yes, clone returns a raw pointer...
// it puts the burden on the caller as for how to wrap it
//   It is to obey the `Cloneable` concept as described in 
// the Boost Pointer Container library linked above
struct Cloneable
{
  virtual ~Cloneable() {}
  virtual Cloneable* clone() const = 0;
};

struct Derived: Cloneable
{
  virtual Derived* clone() const { new Derived(*this); }
};

void scoped()
{
  scoped_ptr<Cloneable> c(new Derived);
} // memory freed here

// illustration of the moved semantics
unique_ptr<Cloneable> unique()
{
  return unique_ptr<Cloneable>(new Derived);
}

void shared()
{
  shared_ptr<Cloneable> n1(new Derived);
  weak_ptr<Cloneable> w = n1;

  {
    shared_ptr<Cloneable> n2 = n1;          // copy

    n1.reset();

    assert(n1.get() == 0);
    assert(n2.get() != 0);
    assert(!w.expired() && w.get() != 0);
  } // n2 goes out of scope, the memory is released

  assert(w.expired()); // no object any longer
}

void container()
{
  ptr_vector<Cloneable> vec;
  vec.push_back(new Derived);
  vec.push_back(new Derived);

  vec.push_back(
    vec.front().clone()         // Interesting semantic, it is dereferenced!
  );
} // when vec goes out of scope, it clears up everything ;)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:
C++

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • chrmoe

    chrmoe

    7 Kasım 2006
  • graham025

    graham025

    25 NİSAN 2006
  • Malwarebytes

    Malwarebytes

    22 Temmuz 2007