2012-06-29 2 views
2

싱글 톤 템플리트가 실제로 싱글 톤이 아닐 수도 있다는 말을 들었습니다. 하나 이상의 객체를 만드는 방법이 있습니다. 내가 그것을 고치는 방법을 물었을 때, 나는 무시 당했다. 그래서 여기에 와서 왜 내 싱글 톤 템플릿 클래스가 정말로 싱글 톤인지 묻습니다.내 싱글 톤 템플릿이 실제로 싱글 톤입니까?

class Console : public Singleton<Console> 
{ 
}; 
+8

당신이'콘솔 C1, C2를 컴파일 해봤;'? –

+0

나는 방금 단일 인스턴스를 우회하는 한 가지 방법을 발견했습니다.콘솔 c1로 콘솔을 초기화하면; 나는 Singleton 클래스의 인스턴스 포인터에 c1의 Console 인스턴스와 Console의 두 번째 인스턴스를 가지고있다. – ctor

답변

2

사용하십시오 지역 정적 변수 구현하는 싱글 톤 패턴 : 훨씬 적은 코드와는 별도로

template <class T> 
class Singleton 
{ 
    static T* getInstancePtr() 
    { 
     static T instance; // <-- HERE 

     return &instance; 
    } 
}; 

, 또한 스레드 안전 보장됩니다. Singleton<X>::getInstancePtr()에 대한 첫 번째 호출에서 생성되고 연속 호출은 하나의 인스턴스를 가져옵니다. 당신이 스레드 당 하나 개의 인스턴스를 원하는 경우

또는 대신 thread_local 사용할 수 있습니다

template <class T> 
class Singleton 
{ 
    static T* getInstancePtr() 
    { 
     thread_local T instance; // <-- HERE 

     return &instance; 
    } 
}; 
3

는 싱글 왜 당신은 보장 할 수있는 한 가지 간단한 이유 예정이다 스레드 - 안전 - : 내가 원하는

#ifndef SINGLETON_H_ 
#define SINGLETON_H_ 

template <class T> 
class Singleton 
{ 
private: 
static T* instance; 

protected: 
    Singleton<T>() 
    { 
    } 

public: 
    static T* getInstancePtr() 
    { 
     if (instance == 0) 
      instance = new T(); 

     return instance; 
    } 
}; 

template <class T> T* Singleton<T>::instance = 0; 

#endif 

이것은 다음 클래스에 의해 상속 그래서 같은 싱글이 될 수 있습니다 .

두 개 이상의 스레드가 getInstancePtr을 동시에 호출하면 스레드 스와핑에 따라 두 개 이상의 인스턴스가 종료 될 수 있습니다.

+0

OP의 질문은 멀티 스레딩과 관련이 없으며 싱글 톤은 멀티 스레딩에 고유하지 않습니다. – phonetagger

4

기본 생성자는 protected입니다. 파생 클래스가 액세스 할 수 있으므로 컴파일됩니다.

Console c1, c2; 
+2

다른 사람들의 의견을 답변으로 다시 게시하지 마십시오. –

+2

@ 니콜라이 - 왜 그게? –

+0

@Charles Q가 편집되었습니다. 정의가 있습니다. @ Nikolai'std :: string str;'을 작성한 적이 있습니까? 나도 했어. – jrok

0

다중 스레드 환경에서 작업하려면 다른 해결책이 필요합니다. 특정 언어 기능을 사용하여 다중 스레드가있는 상태에서 하나의 오브젝트 인스턴스 만 작성되도록해야합니다. 보다 일반적인 솔루션 중 하나는 Double-Check Locking 관용구를 사용하여 개별 스레드가 동시에 단일 인스턴스의 새 인스턴스를 작성하지 못하게하는 것입니다.

+0

OP의 질문은 멀티 스레딩과 관련이 없으며 싱글 톤은 멀티 스레딩에도 고유하지 않습니다. – phonetagger

0

멀티 스레딩의 문제점 이외에도 두 가지 인스턴스를 만들 수있는 경우가있었습니다. 그래서

Console c1; 

처럼

class Console : public Singleton<Console> 
{ 
}; 

아래의 클래스 콘솔을 초기화하는에 의하여 나는 콘솔의 두 인스턴스, 싱글 톤 클래스 내에서 개최 된 인스턴스 포인터의 하나는 C1 개체 자체 내에서 하나 결말이었다. 싱글 톤 클래스를 다음과 같이 변경하여이 문제를 해결했습니다.

#ifndef SINGLETON_H_ 
#define SINGLETON_H_ 

template <class T> 
class Singleton 
{ 
private: 
    static T* instance; 

protected: 
    Singleton<T>() 
    { 
     if (instance == 0) 
      instance = static_cast<T*>(this); 
    } 

public: 
    static T* getInstancePtr() 
    { 
     return instance; 
    } 
}; 

template <class T> T* Singleton<T>::instance = 0; 

#endif 

멀티 스레딩 문제 외에도, 이제는 싱글 톤 클래스가 여러 인스턴스를 생성 할 가능성이 적습니다.

+0

그건 해결되지 않습니다. 'instance'는 생성 된 첫 번째 인스턴스를 가리 키지 만 파생 클래스의 생성자를 private로 설정하지 않는 한 원하는만큼 파생 클래스 인스턴스를 기본 인스턴스로 만들 수 있습니다. http://ideone.com/Y0zPo – jrok

+1

저는 그것을 고쳤고 그것을 상속받은 클래스에 싱글 톤을 친구로 추가했습니다. 감사 :) – ctor

1

개인적인 생성자와 소멸자를 만들기 위해 동일한 싱글 톤 템플릿을 사용했지만 사용자에게 맡깁니다. 사용자는 싱글 톤 클래스와 친구가되어야하지만, 원하는대로 가깝기 때문에 싱글 톤으로 사용할 수 있습니다. 아직 스레드 세이프가 아니지만 다중 인스턴스 문제를 '해결'합니다.