1

我有一个关于抛出表达式和复制构造函数的问题。

#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 表达式中,当操作数是非易失性自动对象(函数或 catch 子句参数除外)的名称时,其范围不超出最内层封闭 try 块的末尾(如果有的话),从操作数到异常对象(15.1)的复制/移动操作可以通过将自动对象直接构造到异常对象中来省略

4

2 回答 2

2

未定义异常对象的复制(或在 C++11 中移动),但它必须是可复制的(或在 C++11 中可移动),并且实现可以复制(或移动)它任意多次搞笑。

于 2012-09-10T17:14:32.350 回答
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.
于 2012-09-10T18:20:47.827 回答