2014-02-14 1 views
2

을 건설하고 난 다음 코드가 : 이것은 다음과 같은 출력싱글 두 번

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cassert> 
#include <memory> 

class Logger : public std::ofstream 
{ 
public: 
    explicit Logger(std::string const& filename = "log.txt"): 
     std::ofstream(filename.c_str()) 
    { 
     assert(*this); 

     *this << "-- log file start --\n" << std::endl; 
    } 

    Logger::~Logger() 
    { 
     *this << "\n-- log file end --" << std::endl; 

     this->close(); 
     this->clear(); 
    } 
}; 

Logger logger; 

template<class T> 
class NotCopyable 
{ 
public: 

    NotCopyable() { } 
    ~NotCopyable() { } 

private: 

    NotCopyable(NotCopyable const&); 
    NotCopyable const& operator=(NotCopyable const&); 
}; 

template<class T> 
class Singleton : public NotCopyable<Singleton<T> > 
{ 
public: 

    static T& GetInstance() 
    { 
     if (!instance) 
     { 
      logger << "Initialize Singleton" << std::endl; 

      instance.reset(new T()); 
     } 

     return *instance; 
    } 

protected: 

    Singleton() { } 
    virtual ~Singleton() { } 

private: 

    static std::unique_ptr<T> instance; 
}; 

template<class T> 
std::unique_ptr<T> Singleton<T>::instance; 

class Factory : public Singleton<Factory> 
{ 
public: 

    Factory() { logger << "Factory constructor" << std::endl; } 
    ~Factory() { logger << "Factory destructor" << std::endl; } 

    void Blargl() { logger << "Blargl" << std::endl; } 

}; 

bool DoStuff() 
{ 
    Factory::GetInstance().Blargl(); 

    return true; 
} 

bool Thingy = DoStuff(); 

int main(int, char*[]) 
{ 
    logger << "Start main()" << std::endl; 

    Factory::GetInstance().Blargl(); 

    logger << "End main()" << std::endl; 
} 

:

-- log file start -- 

Initialize Singleton 
Factory constructor 
Blargl 
Start main() 
Initialize Singleton 
Factory constructor 
Blargl 
End main() 
Factory destructor 

-- log file end -- 

내가 바보가 된 기분,하지만 공장은 두 번 대신에 건설되고있는 이유를 볼 수 없습니다 일단. 무슨 일 이니?

+3

이유 # 57 왜 그냥 하나는 싱글의 지옥을 친다 만듭니다. 단순히 글로벌을 사용했다면 이미 끝났을 것입니다. – cHao

+0

코드 실행을 시도했지만 문제가 중복되지 않았습니다. –

+0

흠. Visual Studio 2012 (Express Edition)를 사용하고 있습니다. – user673679

답변

4

코드를 실행하려고 시도했지만 Apple llvm 5.0 OSX에서 설명한 것과 동일한 문제가 발생했습니다. 당신은 getInstance() 메소드 내부의 정적 인스턴스 변수를 정의하면
그것은 잘 작동 :

static T& GetInstance() 
{ 
    static std::unique_ptr<T> instance 
    if (!instance) 
    { 
     logger << "Initialize Singleton" << std::endl; 

     instance.reset(new T()); 
    } 

    return *instance; 
} 

나는 당신이 당신의 코드에서이 문제가 싱글 톤의 초기화와 실행의 지정 순서라고 생각 :: 인스턴스를 선언 지점 (기본 생성자)에서 가져오고 GetInstance() 메서드에서 할당합니다. main() 내부의 Singleton<Factory>::instance

  • 새로운 GetInstance() 전화의

    1. GetInstance() 전화
    2. 전화 DoStuff()에서 기본-건설 : 내가 무엇을 말하고있는 것은 맞다면
      그래서, 실행 순서는 아마 같은 것입니다

    편집 : 다음 이론으로 내 이론을 테스트했습니다. E :

    template <typename T> 
    class Ptr { 
    public: 
        Ptr() 
        : p() { 
         std::cout << "Initalizing Ptr" << std::endl; 
        } 
    
        std::unique_ptr<T> p; 
    }; 
    
    
    
    template<class T> 
    class Singleton : public NotCopyable<Singleton<T>> { 
    public: 
        static T& GetInstance() 
        { 
         if (!instance.p) 
         { 
          std::cout << "Initalizing Singleton" << std::endl; 
          logger << "Initialize Singleton" << std::endl; 
          instance.p.reset(new T()); 
         } 
        return *instance.p; 
    } 
    
    protected: 
        Singleton() { } 
        virtual ~Singleton() { } 
    
    private: 
        static Ptr<T> instance; 
    }; 
    
    template<class T> 
    Ptr<T> Singleton<T>::instance; 
    

    출력 :

    1. Initalizing 싱글
    2. Initalizing의 PTR
    3. Initalizing 싱글
  • +0

    고마워, 그 트릭을 할 것으로 보인다. – user673679

    관련 문제