2014-05-24 1 views
1

최근 Andrei Alexandrescu의 Modern C++ Design을 읽었습니다. 6. 장을 읽은 후에 회사에서 싱글 톤에 대해 걱정하기 시작합니다. 경험 많은 팀장이 싱글 톤 (singletons)과 같은 핵심 도우미 라이브러리를 작성하기 때문에 .... 나는 싱글 톤을 다루는 방식이 죽은 참조 문제를 처리하는지 질문했다. C 코어 언어에 의해 주어진 at_exit 함수 호출을 사용했다면?C++ 11 핵심 언어가 Singleton Dead Reference를 처리합니까?

그는 C++ 11에 싱글 톤 지원이 있으며 CTOR과 DTOR를 연속적으로 실행하여 아무런 참조 문제도 발생하지 않을 것이라고 말했습니다. 사용자는 동기화에 대처할 필요가 없습니다.

심지어 내가 인터넷에서 그를 확인하는 정보를 찾을 수 없다는 두려운 소리. 그러니 C++ 11이 싱글 톤을위한 Dead Reference Problem을 다루는 지 말해 주시고, 그렇다면 어둠의 마법이 어떻게 돌아가는지 조금 설명해주십시오. 다음과 같이

+2

* 싱글 톤 *에 대한 * 데드 레퍼런스 문제는 무엇입니까? 끔찍한 고통처럼 들리네. C++ 11에서는 함수 내에서 정적 변수의 생성이 스레드 세이프 (threadafe safe)가 될 것이라는 보증을 추가했으며, 처음에는 함수가 호출 될 때 생성됩니다. 이것은 아마도 당신이 찾고있는 것입니다. – Praetorian

+0

나는 현재 문제의 제목을 6.5 절에서 언급 한 책과 같은 제목으로 사용하고있다. 책과 같은 제목을 사용하는 것이 더 나을 것 같아서 미안해. 나쁘게 들리더라도 내 가난한 영국인도 영어를 할 수있어. –

답변

5

아마 팀 리더가 구현 싱글 대해 이야기 :

T &get_value() { 
    static T val; 
    return val; 
} 

를이 경우, 표준이 보증을 제공합니다.

구현이있다 : 첫 번째는 val 개체 즉 여러 스레드 6.7/4에서 동시에 발생하는 경우에도, 정확히 한번 프로그램 실행의 흐름은 로컬 정적 변수의 선언을 통과 처음 구성 될 것이라는 것이다 구현시 네임 스페이스 범위 (3.6.2)에서 정적 또는 스레드 저장 기간을 사용하여 변수를 정적으로 초기화 할 수있는 것과 동일한 조건에서 정적 또는 스레드 저장 기간을 사용하여 다른 블록 범위 변수의 초기 초기화를 수행 할 수 있습니다. 그렇지 않으면 이러한 변수는 처음 제어가 선언을 통과 할 때 초기화됩니다. 그러한 변수는 초기화 완료시 초기화 된 것으로 간주됩니다. 예외를 throw하여 초기화가 끝나면 초기화가 완료되지 않으므로 다음에 컨트롤이 선언에 들어올 때 다시 시도됩니다. 변수가 초기화되는 동안 컨트롤이 동시에 선언에 들어가면 동시 실행은 초기화 완료를 기다려야합니다.

정적 초기화는이 경우에, 당신은 걱정하지해야 constexpr 생성자가없는 너무 오래 T로, 상수의 경우에 허용 (단, 전체 규칙 3.6.2 읽기 코드와 관련된 일부 엣지 케이스).

제 보장 정적 저장 기간이 모든 변수들은 구조 3.6.3/1의 역순으로 파괴 될 것이라는 것이다 : 초기화 된 개체

소멸자 (12.4) (즉,) (그 수명 3.8 개체 std :: exit (18.5)를 호출 한 결과 정적 저장소 기간이있는 저장소가 시작된 경우 (main에서 반환 한 결과로 호출 됨). 지정된 thread 내의 thread 스토리지 존속 기간을 가지는 초기화 된 오브젝트의 소멸자는, 그 thread의 초기 함수로부터 돌아 왔을 때, 및 그 thread가 std :: exit를 호출 한 결과로서 불려갑니다. 스레드 내에서 스레드 저장 기간을 가진 초기화 된 모든 객체에 대한 소멸자의 완료는 정적 저장 기간이있는 객체의 소멸자가 시작되기 전에 순서가 지정됩니다. 생성자의 완료 또는 스레드 저장 기간이있는 객체의 동적 초기화가 다른 스레드보다 먼저 시퀀싱되면 두 번째 소멸자의 완료는 첫 번째 소멸자의 초기화 전에 시퀀싱됩니다. 정적 저장 기간을 가진 객체의 생성자 완료 또는 동적 초기화가 다른 객체보다 먼저 시퀀싱되면 두 번째 소멸자의 완료는 첫 번째 소멸자의 초기화 전에 시퀀싱됩니다.[주의 :이 정의는 동시 파괴를 허용한다. - end note] 객체가 정적으로 초기화되면 객체가 동적으로 초기화 된 것과 같은 순서로 객체가 파괴됩니다. 배열 또는 클래스 유형의 객체의 경우 해당 객체의 모든 하위 객체가 파괴되어 하위 객체의 생성 중에 정적 저장 기간이 초기화 된 블록 범위 객체가 파기됩니다. 정적 또는 스레드 저장 기간을 가진 객체의 파기가 예외를 통해 종료되면 std :: terminate가 호출됩니다 (15.5.1).

이 단락은 동시 생성시 정적 객체를 동시에 파괴 할 수있는 범위가 많이 있지만, 파괴의 주된 이유는 파괴가 역순으로 발생한다는 것입니다. 함께

는, 이러한 평균은 T val이 단일 기능의 또 다른 몇 가지 U val에 따라 달라집니다 경우 U val 항상 T val 전에 구성과 T val 후 파괴된다는 것을 의미합니다, 그래서 전반적으로,이 (하지 않는 한 싱글 톤을 구현하는 안전한 방법입니다 당신은 매우 미친 짓하고 있어요).