2017-04-25 1 views
3

로컬 정적 객체의 생성자에서 throw 된 예외를 어떻게 사용해야합니까? 내가 알고있는 것처럼, 두 번째 foo 메소드를 호출의 경우, a만큼 완벽하게 구성 객체를 처리하고, 생성자가 호출되지 객체로컬 정적 객체 및 예외

class A 
{ 
public: 
    A() {throw runtime_error("Ooops");} 
}; 

void foo() 
{ 
    static A a = A(); 
    cout << "Continue" << endl; 
} 

int main(void) 
{ 
    try 
    { 
     foo(); 
    } 
    catch(...) 
    { 
    } 
    foo(); // Prints continue 
    return 0; 
} 

예를 들어 나는 다음 코드했다. (더 이상, 그것은 소멸자 a 첫 번째 예외 던지기로 인해 호출되지 않습니다)

+3

아니요, 이해가 잘못되었습니다. 당신은 스스로 (trivially) 이것을 시도 할 수있었습니다 (https://wandbox.org/permlink/0zqV3BglWpVZSgRM). –

+0

예외를 던지고 생성자의 실행을 종료 한 경우 (객체 생성을 완료하지 않은 경우)'a '가 완전히 생성되는 것을 어떻게 예상합니까? – Rogus

+0

'정적 A a = A();'왜 이것을 했습니까? 복사 초기화가 필요한 이유는 무엇입니까? –

답변

4

그렇다면 컴파일러 버그입니다.

는 (단, VTT claims that this code produces the expected result with Visual Studio 2015, 나는 그렇게는 결과를 두 번 확인해 보시기 바랍니다.)

다음은 표준 명령 한 행동입니다 :

[C++14: 6.7/4]: 모든 블록의 0 초기화 (8.5) 정적 저장 기간 (3.7.1) 또는 스레드 저장 기간 (3.7.2)이있는 -scope 변수는 다른 초기화가 수행되기 전에 수행됩니다. 해당되는 경우 정적 저장 기간이있는 블록 범위 엔터티의 상수 초기화 (3.6.2)는 해당 블록이 처음 입력되기 전에 수행됩니다. 구현은 네임 스페이스 범위 (3.6.2)에서 정적 또는 스레드 저장 기간을 사용하여 변수를 정적으로 초기화 할 수있는 것과 동일한 조건에서 정적 또는 스레드 저장 기간을 사용하여 다른 블록 범위 변수의 초기 초기화를 수행 할 수 있습니다. 그렇지 않으면 이러한 변수는 처음 제어가 선언을 통과 할 때 초기화됩니다. 그러한 변수는 초기화 완료시 초기화 된 것으로 간주됩니다. 예외를 throw하여 초기화가 종료되면 초기화가 완료되지 않으므로 다음에 컨트롤이 선언에 들어갈 때 다시 시도됩니다. 변수가 초기화되는 동안 컨트롤이 동시에 선언에 들어가면 동시 실행은 초기화 완료를 기다려야합니다. 변수가 초기화되는 동안 컨트롤이 반복적으로 선언을 다시 입력하면 동작은 정의되지 않습니다. [...]

GCC 6.3.0 correctly attempts to reconstruct the A (그리고 다시 발생).


더 이상, 그것은

없음 호출되지 않은 때문에 첫 번째 예외 던지기의 소멸자처럼 보인다, 그것은되지 않습니다. 처음부터 결코 성공적으로 생성되지 않은 객체는 파괴 할 수 없습니다.

[C++14: 15.2/2]: 초기화 또는 파괴 예외로 종료 소멸자 (노조 같은 클래스의 변형 회원 제외) 완전 구성 하위 객체의 모든 실행 한 것입니다 스토리지 기간의 객체, 즉를 들면, 주 생성자 (12.6.2)가 실행을 완료하고 소멸자가 아직 실행을 시작하지 않은 하위 객체.마찬가지로 개체의 비 위임 생성자가 실행을 완료하고 해당 개체의 위임 생성자가 예외로 종료되면 개체의 소멸자가 호출됩니다. 개체가 new-expression에 할당 된 경우 일치하는 할당 해제 기능 (3.7.4.2, 5.3.4, 12.5)이 호출되면 개체가 사용하는 저장소를 해제합니다. 그런데


,이 문제가 해결되지 않습니다,하지만 당신은 단지 다음과 같이 작성한다 : 임시에서

static A a; 

복사 - 초기화가 무의미하다.

+1

6.7/4 "예외가 발생하여 초기화가 끝나면 초기화가 완료되지 않았으므로 다음에 컨트롤이 선언에 들어올 때 다시 시도됩니다." – aschepler

+0

@aschepler : thanks –

+0

@BoundaryImposition, 연결된/dettached 디버거에서 프로그램의 동작이 다릅니다 (msvc 2015 의미). dettached 디버거 프로그램이 실패 할 경우 – LmTinyToon

2

정적 로컬 변수의 각 인스턴스는 또한 암시 적으로 정적 변수가 생성 된 후 true로 설정됩니다 전역 부울 변수를 만듭니다. 다음에 메서드가 호출 될 때보 다 생성자가 throw하는 경우 정적 변수를 만드는 또 다른 시도가 있습니다.

+0

그래,하지만 OP는 그렇지 않다는 것을 보여 줬어. –

+0

흠, 그는 심지어 자신의 코드를 실행하지 않은 것 (그리고 실제로 그것은 예기치 않은 예외가 있습니다), [작업 예제] (http://ideone.com/4HZSTO)를 참조하십시오 VS2015도 잘 동작합니다. – VTT

+0

흥미 롭습니다! 확인을 위해 VS2015가 없습니다. –