내 친구가 왜 세계 전역의 정적 객체보다 싱글 톤의 사용을 선호해야 하는가? 내가 설명하기 시작한 방법은 싱글 톤이 상태 대 정적 전역 객체를 가질 수 없다는 것이 었습니다.하지만 확실하지 않았습니다. 왜냐하면 C ++의이 때문에 .. (C #에서 왔습니다)
어떤 이점이 다른 것보다 무엇입니까? (C ++에서)
사실, C ++에서 선호하는 방법은 로컬 정적 객체입니다.
Printer & thePrinter() {
static Printer printer;
return printer;
}
이것은 기술적으로는 싱글 톤이지만,이 함수는 클래스의 정적 메서드 일 수도 있습니다. 따라서 전역 정적 객체와 달리 사용하기 전에 생성 된 순서대로 생성 될 수 있으므로 하나의 전역 객체가 다른 객체를 사용할 때 일관성없이 실패 할 수 있습니다. 매우 일반적인 시나리오입니다.
호출을 통해 새로운 인스턴스를 생성하여 싱글 톤을 수행하는 일반적인 방법보다 나은 점은 무엇입니까?new
그 객체 소멸자는 프로그램의 끝에서 호출 될 것입니다. 동적으로 할당 된 싱글 톤에서는 발생하지 않습니다.
또 하나의 긍정적 인 측면은 싱글 톤이 생성되기 전에 싱글 톤에 접근 할 수있는 방법이 없다는 것입니다. 다른 정적 메소드 나 서브 클래스에서도 가능합니다. 디버깅 시간을 절약 해줍니다.
C ++에서 서로 다른 컴파일 단위로 정적 객체를 인스턴스화하는 순서는 정의되지 않았습니다. 따라서 하나의 글로벌이 생성되지 않은 다른 글로벌을 참조하여 프로그램을 폭파 할 수 있습니다. 싱글 톤 패턴은 생성자를 정적 멤버 함수 또는 자유 함수에 묶음으로써이 문제를 제거합니다.
알맞은 요약이 있습니다.이리.
cout
과cin
전에 특별히 건설되도록 지정되어있다.main()
표준에 의해. 다른 전역 개체는이 치료를받지 못합니다. 또한 스레드 안전 싱글 톤 구현이 존재하며 자신을 작성하는 것이 어렵지 않습니다. 이중 구조를 방지하기 위해 이중 잠금 장치 만 있으면됩니다. 개인적으로 나는 싱글 톤을 피하려고 노력한다. 패턴이 과용된다고 생각한다. 그러나 당신의 C ++ 지식의 부족은 나를 downvote 할 이유가 없습니다. - rlbond
내 친구가 왜 세계 전역의 정적 객체보다 싱글 톤의 사용을 선호해야 하는가? 내가 설명하기 시작한 방법은 싱글 톤이 상태 대 정적 전역 객체를 가질 수 없다는 것이 었습니다.하지만 확실하지 않았습니다. 왜냐하면 C ++의이 때문에 .. (C #에서 왔습니다)
정적 전역 객체는 C #에서도 상태를 가질 수 있습니다.
class myclass {
// can have state
// ...
public static myclass m = new myclass(); // globally accessible static instance, which can have state
}
어떤 이점이 다른 것보다 무엇입니까? (C ++에서)
싱글 톤은 코드를 손상시키고 전역 정적 인스턴스는 그렇지 않습니다. 그래서 이미 싱글 톤 문제에 관해 수많은 질문이 있습니다.여기 하나있어.,그리고 또 다른,또는 다른.
즉, 싱글 톤은 두 가지를 제공합니다.
첫 번째 요점 만 원하면 전역 적으로 액세스 할 수있는 객체를 만들어야합니다. 과왜우리는 둘째를 원할 것입니까? 우리는하지 않는다.알고있다앞으로 우리 코드가 어떻게 사용될 수 있는지 미리 알아 두어야합니다. 그렇다면 유용한 기능을 제거하는 이유는 무엇입니까? 우리는 보통잘못된우리는 "나는 단지 하나의 인스턴스 만 필요합니다"라고 예측할 때. 그리고 "나는 단지 하나의 인스턴스 만 필요합니다"(정확한 답은 다음과 같습니다.몹시 떠들어 대다하나의 인스턴스), "하나 이상의 인스턴스가 생성되면 응용 프로그램이 제대로 작동하지 않을 수 있습니다. 사용자의 하드 드라이브를 포맷하고 중요한 데이터를 인터넷에 게시 할 것입니다"(대답은 다음과 같습니다. 앱이 고장 났지만만약그것은 그렇지 않습니다, 그렇습니다, 싱글 톤은 여러분이 필요로하는 것입니다)
cout
과cin
, 이것들은 표준에 의해 정의 된 특별한 경우이다. - rlbond
이유 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();
}
};
전역 정적 객체에 대한 Singleton의 또 다른 이점은 생성자가 private이기 때문에 "하나만있을 수 있습니다"라는 매우 명확한 컴파일러 강제 지시문이 있다는 것입니다.
비교해 보면 전역 정적 객체의 경우이 객체의 추가 인스턴스를 만드는 개발자가 코드를 작성하는 것을 멈추게하는 요소는 없습니다.
추가 제한 조건의 이점은 오브젝트가 어떻게 사용될 것인지에 대한 보증을한다는 것입니다.
Singleton ( "처음 사용할 때 생성") 관용구를 사용하면정적 초기화 순서 실패
C ++에서는 실제 유용성면에서이 둘 사이에 엄청난 차이가 없습니다. 전역 객체는 당연히 고유 한 상태를 유지할 수 있습니다 (다른 전역 변수와도 연관 될 수 있지만, 권장하지는 않습니다). 글로벌 또는 싱글 톤을 사용하려는 경우 (그리고 그렇게하지 않을 많은 이유가 있습니다) 글로벌 객체에 싱글 톤을 사용하는 가장 큰 이유는 싱글 톤을 사용하면 여러 클래스를 상속 받아 동적 다형성을 가질 수 있다는 것입니다 싱글 톤 기본 클래스
좋아요, 정말로 싱글 톤으로가는 두 가지 이유가 있습니다. 하나는 모두가 말하는 정적 순서입니다.
다른 하나는 코드를 사용할 때 누군가가 다음과 같이하지 못하게하는 것입니다.
CoolThing blah;
gs_coolGlobalStaticThing = blah;
또는 더 나쁜 경우 :
gs_coolGlobalStaticThing = {};
캡슐화 측면은 바보와 악의적 인 멍청이로부터 인스턴스를 보호합니다.
Printer
다른 사람이 생성자를 비공개로 만들고 인스턴스를 만들면 인스턴스화되지 않습니다.thePrinter()
친구 기능. - Catskul