[c++] C ++ 싱글 톤 디자인 패턴


8 Answers

싱글 톤이기 때문에, 당신은 보통 그것이 파괴되기를 원하지 않는다.

프로그램이 종료 될 때 해체되고 할당이 해제됩니다. 이는 싱글 톤에 대한 정상적인 원하는 동작입니다. 클래스를 명시 적으로 정리할 수있게하려면 클래스에 클래스를 추가하여 클래스를 깨끗한 상태로 복원하고 다음에 사용 된 시간에 다시 할당 할 수있는 정적 메서드를 추가하는 것이 매우 쉽습니다.하지만 이는 클래스의 범위를 벗어납니다. "고전적인"싱글 톤.

Question

최근에 나는 C ++을위한 Singleton 디자인 패턴의 구현 / 구현에 부딪 혔습니다. 그것은 다음과 같이 보입니다 (저는 이것을 실제 사례에서 채택했습니다) :

// a lot of methods are omitted here
class Singleton
{
   public:
       static Singleton* getInstance( );
       ~Singleton( );
   private:
       Singleton( );
       static Singleton* instance;
};

이 선언에서 인스턴스 필드가 힙에서 시작됨을 추론 할 수 있습니다. 이는 메모리 할당이 있음을 의미합니다. 나에게 완전히 불분명 한 점은 정확히 메모리가 할당 해제 될 때인 것인가? 아니면 버그와 메모리 누수가 있습니까? 구현에 문제가있는 것처럼 보입니다.

내 주요 질문은 올바른 방법으로 구현하는 것입니다.




여기에 많은 답변이 있으며 잠시 전에 질문을 받았지만 다음을 추가하고 싶습니다. Alan과 Paul Ezust에게 주어집니다. ( C ++에서 Qt로 패턴을 디자인하는 데 대한 소개 )

Singleton 패턴은 생성 된 인스턴스의 수나 유형을 제한하고자하는 상황에서 사용되는 특수한 팩토리입니다. 아래에 정의 된 CustomerFactory :: instance () 메소드는 싱글 톤 팩토리의 예입니다. 필요한 경우 객체가 생성되지만 메서드가 처음 호출 될 때만 생성됩니다. 후속 호출에서는 항상 동일한 객체에 대한 포인터를 반환합니다.

CustomerFactory* CustomerFactory::instance(){
   static CustomerFactory* retval = 0;
   if (retval == 0) retval = new CustomerFactory(qApp);          1
   return retval;
}

1 QApplication이 종료 될 때이 오브젝트와 모든 하위 오브젝트가 정리되도록합니다.

메모리 누수가 발생하지 않도록 힙 오브젝트를 처리 할 때 중요합니다. QObjects의 상위 - 하위 관계를 사용하여이 점에 도움이 될 수 있습니다.




다음은 쉬운 구현입니다.

#include <Windows.h>
#include <iostream>

using namespace std;


class SingletonClass {

public:
    static SingletonClass* getInstance() {

    return (!m_instanceSingleton) ?
        m_instanceSingleton = new SingletonClass : 
        m_instanceSingleton;
    }

private:
    // private constructor and destructor
    SingletonClass() { cout << "SingletonClass instance created!\n"; }
    ~SingletonClass() {}

    // private copy constructor and assignment operator
    SingletonClass(const SingletonClass&);
    SingletonClass& operator=(const SingletonClass&);

    static SingletonClass *m_instanceSingleton;
};

SingletonClass* SingletonClass::m_instanceSingleton = nullptr;



int main(int argc, const char * argv[]) {

    SingletonClass *singleton;
    singleton = singleton->getInstance();
    cout << singleton << endl;

    // Another object gets the reference of the first object!
    SingletonClass *anotherSingleton;
    anotherSingleton = anotherSingleton->getInstance();
    cout << anotherSingleton << endl;

    Sleep(5000);

    return 0;
}

하나의 오브젝트 만 작성되고 이후에 매번 오브젝트 참조가 리턴됩니다.

SingletonClass instance created!
00915CB8
00915CB8

여기서 00915CB8은 싱글 톤 Object의 메모리 위치이며, 프로그램이 실행되는 동안 동일하지만 (일반적으로!) 프로그램이 실행될 때마다 다릅니다.

NB 이것은 스레드로부터 안전하지 않습니다. 스레드 안전을 보장해야합니다.




@ Loki Astari의 대답 은 우수합니다.

그러나 싱글 톤 을 사용하는 모든 정적 객체가 더 이상 필요하지 않을 때까지 싱글 톤 이 파괴되지 않는다는 것을 보장 할 수 있어야하는 여러 정적 객체가있는 경우가 있습니다.

이 경우 std::shared_ptr 는 정적 소멸자가 프로그램의 끝에서 호출되는 경우에도 모든 사용자에 대해 싱글 톤 을 유지하는 데 사용할 수 있습니다.

class Singleton
{
public:
    Singleton(Singleton const&) = delete;
    Singleton& operator=(Singleton const&) = delete;

    static std::shared_ptr<Singleton> instance()
    {
        static std::shared_ptr<Singleton> s{new Singleton};
        return s;
    }

private:
    Singleton() {}
};



정적 개체를 삭제해야하는 정적 함수를 작성해야한다고 생각합니다. 응용 프로그램을 닫을 때이 함수를 호출해야합니다. 이렇게하면 메모리 누출이 발생하지 않습니다.




이것은 객체 수명 관리에 관한 것입니다. 소프트웨어에 싱글 톤 이상을 가지고 있다고 가정합니다. 그리고 그들은 Logger 싱글 톤에 의존합니다. 응용 프로그램이 파괴되는 동안 또 다른 싱글 톤 객체가 Logger를 사용하여 파괴 단계를 기록한다고 가정합니다. 로거를 마지막으로 정리해야한다는 것을 보장해야합니다. 따라서이 백서를 확인하십시오. http://www.cs.wustl.edu/~schmidt/PDF/ObjMan.pdf




#define INS(c) private:void operator=(c const&){};public:static c& I(){static c _instance;return _instance;}

예:

   class CCtrl
    {
    private:
        CCtrl(void);
        virtual ~CCtrl(void);

    public:
        INS(CCtrl);



할당하지 않은 또 다른 대안 : 필요에 따라 클래스 C 와 같은 싱글 톤을 만듭니다.

singleton<C>()

~을 사용하여

template <class X>
X& singleton()
{
    static X x;
    return x;
}

이것도 Cătălin의 대답은 자동으로 현재 C ++에서는 thread-safe가 아니지만 C ++ 0x에있게됩니다.




다음과 같이 새 게재 위치를 사용하는 방법 :

class singleton
{
    static singleton *s;
    static unsigned char *buffer[sizeof(singleton)/4 *4] //4 byte align
    static singleton* getinstance()
    {
        if (s == null)
        {
            s = new(buffer) singleton;
        }
        return s;
    }
};



Related