2012-09-10 27 views
1

我有一個關於throw-expressions和copy構造函數的問題。複製構造函數和拋出表達式

#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"; 
    }  
} 

在C++ 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 ... - 在一個拋表達,當操作數是 非易失性自動對象的名稱(除其他功能或附加子句 參數),其作用域不超出最內層的 (如果存在),則可以省略操作數到異常對象(15.1)的複製/移動操作,該操作數從 直接構造自動對象到異常對象中

+1

我覺得這些都不是正確的,除了最後一個。 「錯誤」一詞在所有構造函數之後都會發生。我不知道這是你的錯字還是答案的一部分?你到底在問什麼? –

+1

另外,您可能希望將所有輸​​出放到同一個流中,只是爲了確定這不是您遇到問題的順序的原因。 –

+0

也許有些不好的編譯器會在'throw;'內部的'catch(')'上覆制異常對象嗎? – PiotrNycz

回答

2

未定義對異常對象的複製(或在C++ 11中移動),但它必須是可複製的(或可在C++ 11中移動),且實現可複製(或移動)它的次數他們喜歡吹牛。

+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. 

但請注意:編譯器允許對象的Elid副本(即使它們有副作用的影響)。因此,在這種情況下,編譯器可以優化代碼以在實現特定位置中明確構建它。

另外值得注意:

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.