IT이야기

C ++ 싱글 톤 대 전역 정적 개체

cyworld 2021. 4. 8. 20:50
반응형

C ++ 싱글 톤 대 전역 정적 개체


오늘 제 친구가 왜 전역 정적 객체보다 싱글 톤을 선호해야하는지 물었습니다. 내가 설명하기 시작한 방법은 싱글 톤이 상태를 가질 수 있다는 것입니다. 정적 전역 객체는 그렇지 않을 것입니다 ...하지만 C ++에서 .. 되었기 때문에 저는 확신하지 못했습니다 .. (C #에서 왔습니다)

다른 것보다 장점은 무엇입니까? (C ++에서)


실제로 C ++에서 선호하는 방법은 로컬 정적 객체입니다.

Printer & thePrinter() {
    static Printer printer;
    return printer;
}

기술적으로는 싱글 톤이지만이 함수는 클래스의 정적 메서드 일 수도 있습니다. 따라서 어떤 순서로도 생성 될 수있는 전역 정적 객체와 달리 사용하기 전에 구성되도록 보장하므로 한 전역 객체가 다른 매우 일반적인 시나리오를 사용할 때 일관성없이 실패 할 수 있습니다.

호출하여 새 인스턴스를 생성하는 일반적인 방법보다 더 나은 점은 new개체 소멸자가 프로그램의 끝에서 호출 된다는 것입니다. 동적으로 할당 된 싱글 톤에서는 발생하지 않습니다.

또 다른 긍정적 인 측면은 다른 정적 메서드 나 하위 클래스에서도 단일 항목이 생성되기 전에 액세스 할 수있는 방법이 없다는 것입니다. 디버깅 시간을 절약 할 수 있습니다.


C ++에서는 다른 컴파일 단위에서 정적 개체의 인스턴스화 순서가 정의되지 않았습니다. 따라서 하나의 글로벌이 구성되지 않은 다른 글로벌을 참조하여 프로그램을 폭파시킬 수 있습니다. 싱글 톤 패턴은 구성을 정적 멤버 함수 또는 자유 함수에 연결하여이 문제를 제거합니다.

여기에 괜찮은 요약이 있습니다 .


오늘 제 친구가 왜 전역 정적 객체보다 싱글 톤을 선호해야하는지 물었습니다. 내가 설명하기 시작한 방법은 싱글 톤이 상태를 가질 수 있다는 것입니다. 정적 전역 객체는 그렇지 않을 것입니다 ...하지만 C ++에서 .. 되었기 때문에 저는 확신하지 못했습니다 .. (C #에서 왔습니다)

정적 전역 개체는 C #에서도 상태를 가질 수 있습니다.

class myclass {
 // can have state
 // ...
 public static myclass m = new myclass(); // globally accessible static instance, which can have state
}

다른 것보다 장점은 무엇입니까? (C ++에서)

싱글 톤은 코드를 손상 시키지만 전역 정적 인스턴스는 그렇지 않습니다. 이미 싱글 톤의 문제에 대한 수많은 질문이 있습니다. 여기에 하나 , 다른 , 또는 다른 .

간단히 말해 싱글 톤은 두 가지를 제공합니다.

  • 전역 적으로 액세스 가능한 개체
  • 하나의 인스턴스 만 만들 수 있음을 보장합니다.

첫 번째 지점 만 원하면 전역 적으로 액세스 할 수있는 개체를 만들어야합니다. 그리고 우리는 두 번째를 원할까요? 우리는 우리의 코드가 미래에 어떻게 사용 될지 미리 알지 못합니다 . 그런데 왜 그것을 꼼꼼히 정리하고 유용한 기능을 제거할까요? 우리는 "하나의 인스턴스 만 필요합니다"라고 예측할 때 일반적으로 틀립니다 . 그리고 "하나의 인스턴스 만 필요합니다"(정답은 하나의 인스턴스 만드는 것입니다)와 "하나 이상의 인스턴스가 생성되면 어떤 상황에서도 애플리케이션이 올바르게 실행될 수 없습니다." 사이에는 큰 차이가 있습니다. 사용자의 하드 드라이브를 포맷하고 인터넷에서 민감한 데이터를 게시 "(여기에 대한 답은 다음이다 : 대부분의 가능성이 앱이 파손되어 있지만, 경우 그렇지 않다면 예, 싱글 톤이 필요합니다)


전역 정적 객체에 대한 Singleton의 또 다른 이점은 생성자가 비공개이기 때문에 "하나만있을 수 있습니다"라는 매우 명확한 컴파일러 시행 지시문이 있다는 것입니다.

이에 비해 전역 정적 개체와 비교하면 개발자가이 개체의 추가 인스턴스를 만드는 코드를 작성하는 것을 중단 할 수 없습니다.

추가 제약의 이점은 객체가 사용되는 방식에 대한 보증이 있다는 것입니다.


Singleton ( "construct on first use") 관용구를 사용하면 정적 초기화 순서 실패를 피할 수 있습니다.


이유 1 :
싱글 톤은 만들기가 쉽기 때문에 게으른 빌드입니다.
전역으로이를 수행 할 수 있지만 개발자의 추가 작업이 필요합니다. 따라서 기본적으로 전역은 항상 초기화됩니다 (네임 스페이스가있는 일부 특수 규칙 제외).

따라서 개체가 크거나 빌드하는 데 비용이 많이 드는 경우 실제로 사용해야하는 경우가 아니면 빌드하지 않을 수 있습니다.

이유 2 :
초기화 (및 소멸) 순서 문제.

GlobalRes& getGlobalRes()
{
    static GlobalRes instance;  // Lazily initialized.
    return instance;
}


GlobalResTwo& getGlobalResTwo()
{
    static GlobalResTwo instance;  // Lazy again.
    return instance;
}


// Order of destruction problem.
// The destructor of this object uses another global object so
// the order of destruction is important.
class GlobalResTwo
{
    public:
        GlobalResTwo()
        {
            getGlobalRes();
            // At this point globalRes is fully initialized.
            // Because it is fully initialized before this object it will be destroyed
            // after this object is destroyed (Guaranteed)
        }
        ~GlobalResTwo()
        {
            // It is safe to use globalRes because we know it will not be destroyed
            // before this object.
            getGlobalRes().doStuff();
        }
};

In C++, there's not a huge amount of difference between the two in terms of actual usefulness. A global object can of course maintain its own state (possibly with other global variables, though I don't recommend it). If you're going to use a global or a singleton (and there are many reasons not to), the biggest reason to use a singleton over a global object is that with a singleton, you can have dynamic polymorphism by having several classes inheriting from a singleton base class.


OK, there are two reasons to go with a singleton really. One is the static order thing everyone's talking about.

The other is to prevent someone from doing something like this when using your code:

CoolThing blah;
gs_coolGlobalStaticThing = blah;

or, even worse:

gs_coolGlobalStaticThing = {};

The encapsulation aspect will protect your instance from idiots and malicious jerks.

ReferenceURL : https://stackoverflow.com/questions/1463707/c-singleton-vs-global-static-object

반응형