it-swarm.asia

Herhangi biri bana c ++ dilinde Singleton örneği verebilir mi?

Singleton c ++ 'ı aşağıdaki şekilde yazarım:

class A {
    private:
        static A* m_pA;
        A();
        virtual ~A();

    public:
        static A* GetInstance();
        static void FreeInstance();

        void WORK1();
        void WORK2();
        void WORK3();
    }
}

A* A::GetInstance() {
    if (m_pA == NULL)
        m_pA = new A();
    return m_pA;
}

A::~A() {
    FreeInstance()  // Can I write this? are there any potential error?
}

void A::FreeInstance() {
    delete m_pA;
    m_pA = NULL;
}

Teşekkürler! Evan Teran ve sep61.myopenid.com 'un yanıtı doğru ve gerçekten iyi! Benim yolum yanlış, keşke bu kodları yazan herhangi biri saçma hatamı önleyebilsin.

Projemdeki singleton A'da bir akıllı işaretçi vektörü var ve başka bir iş parçacığı da bu vektörü düzenleyebilir, bu nedenle uygulama kapanırken çok fazla CMutex eklesem bile her zaman kararsız hale gelir. Çoklu okuma hatası + tekil hata beni 1 gün boşa harcadı.

// --------------------------------------------- -------------- Yeni bir singleton, aşağıdaki örnekte herhangi bir sorun olduğunu düşünüyorsanız, düzenlemenizi bekliyoruz:

class A {
    private:
        static A* m_pA;
        explicit A();
        void A(const A& a);
        void A(A &a);
        const A& operator=(const A& a);
        virtual ~A();

    public:
        static A* GetInstance();
        static void FreeInstance();

        void WORK1();
        void WORK2();
        void WORK3();
    }
}

A* A::GetInstance() {
    if (m_pA == NULL){
        static A self;
        m_pA = &self;
    }
    return m_pA;
}

A::~A() {
}
35
user25749

Böyle bir statik nesne kullanarak onu silmeye gerek kalmaz:

if(m_pA == 0) {
    static A static_instance;
    m_pA = &static_instance;
}
12
Evan Teran

Neden herkes bir singletonu işaretçi olarak döndürmek istiyor?
Referans olarak iade, çok daha mantıklı gözüküyor!

Hiçbir zaman bir singletonu manuel olarak serbest bırakmamalısınız. Singleton'a kimin referans yaptığını nereden biliyorsun? Bilmiyorsanız (veya garanti edemiyorsanız) hiç kimsenin referansı yoktur (sizin durumunuzda bir işaretçi aracılığıyla), o zaman nesneyi serbest bırakacak hiçbir işiniz yoktur.

Bir fonksiyon yönteminde statik kullanın.
Bu sadece bir kez yaratılıp imha edildiğini garanti eder. Aynı zamanda ücretsiz tembel başlatma verir. 

class S
{
    public:
        static S& getInstance()
        {
            static S    instance;
            return instance;
        }
    private:
        S() {}
        S(S const&);              // Don't Implement.
        void operator=(S const&); // Don't implement
 };

Ayrıca yapıcıyı özel hale getirmeniz gerektiğini de unutmayın .. __ Ayrıca, varsayılan kopya yapıcısını ve atama operatörünü geçersiz kıldığınızdan emin olun, böylece singleton'un bir kopyasını çıkaramazsınız (aksi halde bir singleton olmaz).

Ayrıca şunu da oku:

Doğru nedenlerden dolayı singleton kullandığınızdan emin olmak için.

Her ne kadar genel durumda teknik olarak güvenli değil olsa da, bakınız:
C++ fonksiyonunda statik değişkenin ömrü nedir?

GCC, bunu telafi etmek için açık bir yamaya sahip:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00265.html

191
Martin York

C++ 'daki singleton şu şekilde yazılabilir:

static A* A::GetInstance() {
    static A sin;
    return &sin;
}
4
sep

Sadece kopya kurucu ve atama operatörlerini özel yapmayı unutmayın.

2
Jasper Bekkers

Bu satırı yazmak için herhangi bir neden olduğunu sanmıyorum. Yıkıcı yönteminiz statik değildir ve singleton örneğiniz bu şekilde yıkılmayacaktır. Yıkıcı gerekli olduğunu sanmıyorum, nesneyi temizlemeniz gerekiyorsa, FreeInstance () oluşturduğunuz statik yöntemi kullanın.

Bunun dışında, benim singleton'unuzu kabaca benimkiyle aynı şekilde yaratıyorsunuz.

1
Odd

Meyers tarzı singletonlar için çılgınca bir coşkunun ardından (önceki cevapların bazılarında yerel statik nesneleri kullanarak), karmaşık uygulamalardaki yaşam boyu yönetim sorunlarından tamamen bıktım.

Uygulamanın ilk başlangıcında kasıtlı olarak 'Örnek' yöntemine başvurduğunuzda, istediklerinizde oluşturulduğundan emin olmak için ve daha sonra tahmin edilemeyen (ya da tahmin edilemeyecek şekilde her tür oyunu oynayarak) bulma eğilimindeyim en azından çok karmaşık ve biraz gizli) bir şeylerin yok edilme düzeni.

Elbette YMMV ve bu, singletonun doğasına bağlı olarak biraz zekalı, ancak akıllı singletonlar (ve zekayı çevreleyen diş açma/kilitleme sorunları) ile ilgili çok fazla gözleme, IMO'nun önüne geçti.

1
Will Dean

eğer "Modern C++ Design" okursanız, singleton tasarımının statik bir değişken döndürmekten çok daha karmaşık olabileceğini fark edeceksiniz. 

1
jab

Bu soruları cevaplayabildiğiniz sürece bu uygulama gayet iyi:

  1. nesnenin ne zaman oluşturulacağını biliyor musunuz (yeni yerine statik bir nesne kullanıyorsanız? Bir main () var mı?)

  2. singleton'un yaratıldığı zaman hazır olmayabilecek herhangi bir bağımlılığı var mı? Yeni yerine statik bir nesne kullanırsanız, bu sırada hangi kitaplıkları başlattı? Nesneniz, yapıcıda onları gerektirebilecek ne yapar?

  3. ne zaman silinecek

New () kullanmak daha güvenlidir çünkü nesnenin nerede ve ne zaman oluşturulacağını ve silineceğini kontrol edebilirsiniz. Ama sonra açıkça silmeniz gerekir ve muhtemelen sistemdeki hiç kimse ne zaman yapılacağını bilmiyor. Mantıklı olması durumunda, bunun için atexit () kullanabilirsiniz.

Yöntemde statik bir nesne kullanmak, ne zaman oluşturulacağını veya silineceğini gerçekten bilmediği anlamına gelir. Küresel bir statik nesneyi bir ad alanında da kullanabilir ve getInstance () yönteminden kaçınabilirsiniz;.

Eğer konu kullanırsan, başın büyük belaya girer. Şunlar nedeniyle C++ 'ta kullanılabilir iş parçacığı güvenli singleton oluşturmak neredeyse imkansızdır:

  1. getInstance'daki kalıcı kilit çok ağırdır - her getInstance'taki tam bağlam anahtarı ()
  2. Çift denetimli kilit derleyici optimizasyonları ve önbellek/zayıf bellek modeli nedeniyle başarısız oluyor, uygulanması çok zor ve test etmek imkansız. Mimarlığınızı yakından tanımadığınız ve taşınabilir olmasını istemediğiniz sürece, bunu gerçek bir sistemde yapmaya çalışmam.

Bunlar kolayca Googled olabilir, ancak işte zayıf bellek modelinde iyi bir bağlantı var: http://ridiculousfish.com/blog/archives/2007/02/17/barrier .

Bir çözüm kilitleme kullanmak olacaktır ancak kullanıcıların getInctance () 'dan aldıkları imleci önbelleğe almaları ve getInstance ()' nin ağır olması için hazırlıklı olmaları gerekir.

Diğer bir çözüm, kullanıcıların iplik emniyetini kendileri idare etmelerine izin vermek olacaktır.

Yine bir başka çözüm, basit kilitlemeli bir işlevi kullanmak ve onu new () çağrıldığında kilitlemeden ve kontrol etmeden başka bir işlevle değiştirmek olacaktır. Bu işe yarar, ancak tam uygulama karmaşıktır.

0
n-alexander
//! @file singleton.h
//!
//! @brief Variadic template to make a singleton out of an ordinary type.
//!
//! This template makes a singleton out of a type without a default
//! constructor.

#ifndef SINGLETON_H
#define SINGLETON_H

#include <stdexcept>

template <typename C, typename ...Args>
class singleton
{
private:
  singleton() = default;
  static C* m_instance;

public:
  singleton(const singleton&) = delete;
  singleton& operator=(const singleton&) = delete;
  singleton(singleton&&) = delete;
  singleton& operator=(singleton&&) = delete;

  ~singleton()
  {
    delete m_instance;
    m_instance = nullptr;
  }

  static C& create(Args...args)
  {
    if (m_instance != nullptr)
      {
    delete m_instance;
    m_instance = nullptr;
      }
    m_instance = new C(args...);
    return *m_instance;
  }

  static C& instance()
  {
    if (m_instance == nullptr)
      throw std::logic_error(
        "singleton<>::create(...) must precede singleton<>::instance()");
    return *m_instance;
  }
};

template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;

#endif // SINGLETON_H
0
amightywind

Modellere göre harika bir C++ kütüphanesi var. Farklı desen türleriyle ilgili çok fazla dokümantasyon var bu yüzden çalışmalarına bakın: http://www.cs.wustl.edu/~schmidt/ACE.html

0