复制构造函数和throw-expression

时间:2012-09-10 17:05:34

标签: c++ c++11

我有关于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 ... - 在throw-expression中,当操作数是a的名称时   非易失性自动对象(函数或catch子句除外)   参数)其范围不超出最内层的末端   封闭try-block(如果有的话),复制/移动操作   异常对象(15.1)的操作数可以省略   将自动对象直接构造到异常对象

2 个答案:

答案 0 :(得分: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.

但请注意:允许编译器忽略对象的副本(即使它们有副作用)。因此,在这种情况下,编译器可以优化代码,以在特定于实现的位置显式构造它。

另外值得注意的是:

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.