2012-09-10 5 views
1

throw-expressions 및 복사 생성자에 대한 질문이 있습니다. C에서복사 생성자 및 throw 표현

#include <iostream> 

class Foo 
{ 
public: 
    Foo() { std::cout << "Foo::Foo() \n"; } 
    Foo(const Foo&) { std::cout << "Foo::Foo(const Foo&) \n"; } 
    ~Foo() { std::cout << "Foo::~Foo() \n"; } 
}; 

int main() 
{ 
    try 
    { 
     throw Foo(); 
    } 
    catch (...) 
    { 
     std::cerr << "Error \n"; 
    }  
} 

++ 98/C++ 03, 수행이 코드 인쇄 :

Foo::Foo() 
Error 
Foo::Foo(const Foo&) 
Foo::~Foo() 

다음의 C++ 11 일에 :

Foo::Foo() 
Error 
Foo::Foo(const Foo&) 
Foo::~Foo() 

또는

Foo::Foo()  
Error 
Foo::~Foo() 

이 내용은 C++에서만 나타납니다. 11 :

12.8 복사 및 이동 클래스 오브젝트 [class.copy]

31 ... - 피연산자 함수 이외 비 휘발성 자동 오브젝트의 이름 (인 스로인 식의 또는 catch 절 매개 변수)의 범위가 try-block (있는 경우)의 가장 안쪽에있는 끝을 넘어서지 않으면 피연산자에서 예외 객체 (15.1)로 복사/이동 작업을 생략 할 수 있습니다. 자동 개체를 예외 개체에 직접 생성

+1

나는 그 중 어느 것도 마지막을 제외하고, 바로 없다 생각합니다. 'Error'라는 단어는 모든 생성자 다음에 _ 항상 _ 발생합니다. 그 부분이 오타이거나 대답의 일부인지 나는 모른다. 정확히 무엇을 요구하고 있습니까? –

+1

또한 문제가 발생한 주문의 원인이 아닌지 확인하기 위해 모든 스트림을 동일한 스트림에 출력 할 수 있습니다. –

+0

일부 불량 컴파일러는'throw;'의 경우'catch (...)'에 예외 객체를 복사합니까? – PiotrNycz

답변

2

예외 객체의 복사 (또는 C++ 11에서의 이동)는 정의되어 있지 않지만 복사가 가능해야하며 (C++ 11에서는 이동 가능해야 함) 구현시 여러 번 복사 (또는 이동) 할 수 있습니다. 그들은 funsies를 좋아한다.

+1

또는 예상보다 적은 횟수. –

2

내가 볼 기대 :

Foo::Foo()    // construction 
Foo::Foo(const Foo&) // copy to special throw location 
Error     // catch and print error 
Foo::~Foo()   // at the end of the catch block the exception object is destroyed. 

or 

Foo::Foo()    // As above but compiler has optimized the copy out. 
Error 
Foo::~Foo() 

그 이유 :

throw Foo(); // Creates a local temporary object. 
       // The throw then copies (moves) the local temporary to an implementation 
       // specific location to preserve it while the stack is unwound. 

그러나 참고 : 컴파일러는 (그들이 측면에 영향을 미치는 경우에도) 객체의 복사본을 제거하다 할 수있다. 따라서이 상황에서 컴파일러는 코드를 구현 특정 위치에서 명시 적으로 생성하도록 최적화 할 수 있습니다.

또한 가치는 주목할 :

catch (Foo e)   // Copies the exception object from the implementation specific location 
         // to e so it can be used in the try block. Note this may also result in 
         // object slicing if you don;t catch the exact type. 

catch (Foo const& e) // No copy required as you are using a reference 
         // Thus no chance of slicing.