[C++] 싱글톤 디자인 패턴(Singleton Design Pattern)
프로파일러를 만들다 보니 단 하나의 객체를 만들어 사용할 일이 있었다.
싱글톤 디자인 패턴이란?
소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다.
- 위키피디아 -
현대 C++에서 사용하는 방식으로는 클래스 인스턴스를 단 하나 가지는 방식을 사용할 수 있다.
이를 위해 생성자를 막고, 정적 클래스 멤버 함수 안에서 정적 지역 변수로 객체를 생성하여 반환하는 방식이다.
주요 특징
- 인스턴스 유일성: 싱글톤 패턴을 사용하면 클래스의 인스턴스가 하나만 생성됨을 보장합니다.
- 전역 접근: 인스턴스에 대한 전역적인 접근점을 제공합니다.
- 지연 초기화: 인스턴스가 처음 필요할 때까지 생성되지 않습니다.
class Singleton
{
public:
static Singleton& GetInstance()
{
static Singleton instance;
return instance;
}
private:
Singleton() {}
// 객체는 유일하게 하나만 생성되어야 하기에 복사(대입), 이동(대입) 생성자 비활성화
// 복사, 이동 생성자를 delete로 선언함으로서,
// 프로그래머 실수에 의한 복사, 이동 생성자 호출을 원천에 방지할 수 있음.
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
};
// 출처 : https://computing-jhson.tistory.com/135
객체의 생성을 막기 위해 생성자를 private에 두어 인스턴스가 만들어지는 것을 방지할 수 있다.
static 키워드가 붙은 정적 지역 변수는 C++ 11 이상부터 멀티 스레드 환경에서도 안전하게 초기화된다.
static 키워드가 붙은 정적 멤버 변수와는 다르게, static GetInstace() 함수를 외부에서 초기화할 필요가 없다.
이것이 가능한 이유는 정적 멤버 함수는 인스턴스와 독립적으로 호출되기 때문에 객체의 초기화 상태에 의존하지 않으며
고정된 메모리 위치(코드 영역)에 존재하기 때문에 어디서든 클래스의 이름을 통해 호출할 수 있다.
(물론 extern 또는 헤더 이름을 가지는 파일은 포함하여야 한다.)
객체를 생성할 수 없게 만들어진 싱글톤 클래스의 특성에 맞게 범위 지정 연산자를 통해 클래스 멤버 변수에 직접 접근하여 호출할 수 있다.
static 키워드가 붙은 정적 지역 변수인 Instace는 GetInstace() 함수를 최초 호출 시에 객체가 생성된다.
이 때문에 생성자와 소멸자가 호출되는 시점을 특정할 수 없다.
이 때문에 정적 지역 변수의 초기화 순서에 의존하는 코드 작성을 피해야 할 것이다.
Singleton::GetInstace()
주의할 점은 GetInstace가 참조 형태로 값을 반환하기 때문에 auto 키워드를 통해 사용한다면
이런 식으로 auto에 참조로 추론하게 하여야한다. 일반 auto는 값의 형태로 반환을 받기 때문에
복사된 Instacne를 수정하는 일이 발생할 수 있다.
댓글