在C++中,"throw"和"throw ex"之间有区别吗?

Jos*_*Fox 18 c++ exception-handling

我想问这个问题(也在这里),但这次是关于C++的.

C++之间的区别是什么?

try { /*some code here*/}
catch(MyException& ex)
{ throw ex;} //not just throw
Run Code Online (Sandbox Code Playgroud)

try {  /*some code here*/}
catch(MyException& ex)
{ throw;} //not throw ex
Run Code Online (Sandbox Code Playgroud)

它只是在堆栈跟踪中(在C++中,在任何情况下都不是C#或Java中的标准)?

(如果它有任何区别,我使用MSVS 2008.)

Nav*_*een 32

throw;throw ex;抛出新异常时重新捕获它捕获的同一异常对象.除了创建新异常对象的性能原因之外,它没有什么区别.如果你有一个异常层次结构,其中有一些其他的异常类派生自MyException类,并且抛出异常你已经完成了throw DerivedClassException;它可以被它捕获catch(MyException&).现在,如果您修改此捕获的异常对象并使用throw;异常对象的类型重新抛出它仍将是DerivedClassException.如果您执行throw Ex;了对象切片,则新抛出的异常将是类型MyException.

  • 这取决于前者.在示例中,它将与引用捕获的对象相同(这是标准方式) (3认同)
  • @Phil:不,读15.1/3和15.1/6.即使`ex`是引用,`throw ex;`也不(必然)抛出referand,它使用referand初始化一个临时对象.暂时可能会或可能不会被遗漏.另一方面,`throw;`被指定重用现有的临时. (3认同)
  • @Naveen,如果您通过引用捕获,则不会发生对象切片.如果你抓住了值,切片就已经发生了,虽然在那一点`throw;`会保存你,因为它会重新抛出原来的异常) (2认同)
  • @Phil:检查更有效的C++项目12,确实发生了对象切片.回答我对原始答案的回答. (2认同)

eph*_*ent 14

[ C++ FAQLite§17.9 ] throw;(throw关键字后面没有异常对象)是什么意思?我会在哪里使用它?

您可能会看到如下所示的代码:

class MyException {
public:
  ...
  void addInfo(const std::string& info);
  ...
};

void f()
{
  try {
    ...
  }
  catch (MyException& e) {
    e.addInfo("f() failed");
    throw;
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,语句throw;表示"重新抛出当前异常".这里,函数捕获异常(通过非const引用),修改异常(通过向其添加信息),然后重新抛出异常.通过在程序的重要函数中添加适当的catch子句,可以使用此习惯用法实现一种简单形式的堆栈跟踪.

另一个重新抛出的成语是"异常调度员":

void handleException()
{
  try {
    throw;
  }
  catch (MyException& e) {
    ...code to handle MyException...
  }
  catch (YourException& e) {
    ...code to handle YourException...
  }
}

void f()
{
  try {
    ...something that might throw...
  }
  catch (...) {
    handleException();
  }
}
Run Code Online (Sandbox Code Playgroud)

这个习惯用法允许handleException()重复使用单个函数()来处理许多其他函数中的异常.

[ C++ FAQLite§17.11 ]当我抛出这个对象时,它会被复制多少次?

要看.可能是"零".

抛出的对象必须具有可公开访问的复制构造函数.允许编译器生成任意次数复制抛出对象的代码,包括零.但是,即使编译器从未实际复制抛出的对象,它也必须确保异常类的复制构造函数存在且可访问.

(为了更清楚地说明我认为很明显......)

catch(MyException& ex) { throw ex; }可以复制ex,包括它带来的所有问题; catch(MyException& ex) { throw; }不得.


Man*_*agu 13

如果您有异常层次结构,则throw ex可以对异常进行切片,而throw不会.例如:

#include <iostream> 
#include <string> 

using namespace std; 

struct base 
{ 
  virtual string who() {return "base";} 
}; 

struct derived : public base 
{ 
  string who() {return "derived";} 
}; 

int main() { 
  try { 
    try { 
      throw derived(); // throws a 'derived'
    }  
    catch (base& ex)  
    { 
      throw ex; // slices 'derived' object to be a 'base' object
    } 
  } 
  catch (base& ex) 
  { 
    cout<<ex.who()<<endl; // prints 'base'
  } 
} 
Run Code Online (Sandbox Code Playgroud)

更改throw ex只是throw,你会得到的输出derived,这就是你可能有望得到.


phi*_*red 6

您可以使用throw;表单catch(...)(如果您使用catch(...)捕获它,这是重新抛出的唯一方法).