> 백엔드 개발 > C#.Net 튜토리얼 > C++에서 싱글톤 클래스 구현

C++에서 싱글톤 클래스 구현

黄舟
풀어 주다: 2016-12-12 17:42:30
원래의
1148명이 탐색했습니다.

"Design Pattern"에서 Singleton은 반환 포인터로 작성됩니다.

class Singleton{
public:
    static Singleton* Instance();
protected:
    Singleton();
private:
    static Singleton* _instance;
};
로그인 후 복사

해당 구현 cpp 파일은 다음과 같습니다.

Singleton* Singleton::_instance;
Singleton* Singleton::Instance(){
    if( _instance == 0){
        _instance = new Singleton;
    };
    return _instance;
}
로그인 후 복사

생성자를 설계하는 목적은 다음과 같습니다. protected는 클래스 외부에서 New를 방지하기 위한 것입니다. 누군가가 이를 비공개로 설계할 수 있습니다. 이 클래스의 상속 가능성을 고려한다면 생성자를 protected로 설계하는 것이 좋으며 가상 소멸자도 추가해야 합니다. 다른 사람이 Singleton 객체를 복사하는 것을 방지하려면:

Singleton* pSingleton = Singleton::Instance();
Singleton s1 = *pSingleton;
Singleton s2 = *pSingleton; 
需要将拷贝构造(copy constructor)函数变成 private。
로그인 후 복사

그러나 여기서 문제는 Singleton 객체를 언제 삭제해야 합니까? C++의 기본 원칙에 따르면 객체는 생성된 곳마다 소멸됩니다. 여기에는 Singleton 객체를 삭제하는 destroy 메소드도 있어야 합니다. 삭제하는 것을 잊어버리면 더 번거롭습니다. Instance 함수에도 여러 스레드가 동시에 접근하는 잠금 문제가 있습니다. Instance 기능의 시작과 끝 부분에 Lock과 Unlock을 배치하게 되면 전체 기능의 성능이 많이 떨어지게 됩니다. 이것은 좋은 디자인이 아닙니다.
싱글톤 객체 삭제를 잊어버려서 발생하는 메모리 누수 문제를 방지할 수 있는 작은 변경 사항이 있습니다. 즉, std:auto_ptr을 사용하여 Singleton 객체를 포함하고, 클래스 정적 멤버 auto_ptr 객체를 정의하고, 정적 auto_ptr 변수가 소멸될 때 Singleton 객체를 자동으로 삭제하는 것입니다. 사용자가 싱글톤 개체를 삭제하는 것을 방지하려면 소멸자를 공개에서 보호로 변경해야 합니다. 다음은 헤더 파일 SingletonAutoPtr.h입니다:

#include <memory>
using namespace std;
class CSingletonAutoPtr 
{
private:
    static auto_ptr<CSingletonAutoPtr> m_auto_ptr;
    static CSingletonAutoPtr* m_instance;
protected:
    CSingletonAutoPtr();
    CSingletonAutoPtr(const CSingletonAutoPtr&);
    virtual ~CSingletonAutoPtr(); 
    //allow auto_ptr to delete, using protected ~CSingletonAutoPtr()
    friend class auto_ptr<CSingletonAutoPtr>; 
public:
    static CSingletonAutoPtr* GetInstance();
    void Test();
};
로그인 후 복사

#p#해당 SingletonAutoPtr.cpp는 다음과 같습니다.

#include "SingletonAutoPtr.h"
#include <iostream>
//initial static member vars here 
CSingletonAutoPtr* CSingletonAutoPtr::m_instance = NULL;
auto_ptr<CSingletonAutoPtr> CSingletonAutoPtr::m_auto_ptr;
/////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////
CSingletonAutoPtr::CSingletonAutoPtr()
{
    cout << "CSingletonAutoPtr::CSingletonAutoPtr()" << endl;
    //put single object into auto_ptr object 
    m_auto_ptr = auto_ptr<CSingletonAutoPtr>(this);
}
CSingletonAutoPtr::~CSingletonAutoPtr()
{
    cout << "CSingletonAutoPtr::~CSingletonAutoPtr()" << endl;
}
CSingletonAutoPtr* CSingletonAutoPtr::GetInstance()
{
    //begin lock
    //....
    if(m_instance == NULL)
        m_instance = new CSingletonAutoPtr();
    //end lock
    //...
    return m_instance;
    }
void CSingletonAutoPtr::Test()
{
    cout << "CSingletonAutoPtr::Test()" << endl;
}
로그인 후 복사

호출 방법:

CSingletonAutoPtr* pSingleton = CSingletonAutoPtr::GetInstance();
pSingleton->Test();
로그인 후 복사

Write one C++의 싱글톤에는 그렇게 많은 노력이 필요하다는 것은 우리의 기대 이상입니다. auto_ptr을 사용해 본 적이 없는 사람도 많으며, std:auto_ptr 자체도 객체 소유권 메커니즘을 기반으로 하고 있지만, Apache Log4cxx에는 객체 계산을 기반으로 하여 사용하기 쉬운 auto_ptr이 있습니다. . 좋은 auto_ptr을 사용하기 위해 log4cxx를 사용해야 하는 것은 많은 프로젝트에 좋지 않습니다. 물론 위 예제를 작성하는 데에는 ANSI C++ STL의 std:auto_ptr이면 충분합니다.

#p# 또 다른 아이디어는 GetInstance 함수를 정적 멤버로 설계하는 것이 더 나을 수 있다는 것입니다. 왜냐하면 일반적으로 싱글톤 개체는 크지 않기 때문입니다. 정적 멤버는 항상 메모리를 점유해야 하지만 크지는 않습니다. 문제. 여기서 소멸자는 공개로 설정되어야 합니다. 다음은 헤더 파일 SingleStaticObj.h

class CSingletonStaticObj 
{
private:
    static CSingletonStaticObj m_instance;
protected:
    CSingletonStaticObj();
    CSingletonStaticObj(const CSingletonStaticObj&);
public:
    virtual ~CSingletonStaticObj(); //must public
    static CSingletonStaticObj& GetInstance();
    void Test();
};
    对应的 SingleStaticObj.cpp 文件为:
#include "SingletonStaticObj.h"
#include <string>
#include <iostream>

using namespace std;
CSingletonStaticObj CSingletonStaticObj::m_instance;
CSingletonStaticObj::CSingletonStaticObj()
{
    cout << "CSingletonStaticObj::CSingletonStaticObj()" << endl;
}
CSingletonStaticObj::~CSingletonStaticObj()
{
    cout << "CSingletonStaticObj::~CSingletonStaticObj()" << endl;
}
CSingletonStaticObj& CSingletonStaticObj::GetInstance()
{
    return m_instance;
}
void CSingletonStaticObj::Test()
{
    cout << "CSingletonStaticObj::Test()" << endl;
}
로그인 후 복사

호출 방법입니다.

CSingletonStaticObj& singleton = CSingletonAutoPtr::GetInstance();singleton.Test();
로그인 후 복사

코드 크기 측면에서는 정적 멤버 ref를 사용하는 것이 더 간단한 것 같습니다. 나는 이 방법을 선호한다.

그러나 정적 멤버 싱글톤이 모든 상황에 적합한 것은 아닙니다. 예를 들어, 다른 인스턴스를 반환하기로 동적으로 결정해야 하는 경우에는 GetInstance를 사용할 수 없습니다. 예를 들어 FileSystem::GetInstance는 Windows에서 실행될 때 새 WinFileSystem을 반환해야 할 수 있고 Linux/Unix에서 실행될 때 새 LinuxFileSystem을 반환해야 할 수 있습니다. 이 경우에도 싱글톤 포인터가 포함된 위의 auto_ptr 메서드를 사용해야 합니다.


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿