throw()(或 C++11 中的 noexcept)之所以有用,有两个原因:
- 它允许编译器进行更积极的优化。
- 它告诉函数用户他们可以在自己的非抛出函数中使用这个函数。
非抛出函数对于编写异常安全代码非常重要。例如,编写异常安全operator= 的常用方法是通过不抛出的swap() 函数。
另一方面,其他异常规范是无用的,并且在当前标准中已被合理弃用。它们根本不能与模板很好地混合,而且执行起来成本太高。
现在,如果您在可能实际抛出的函数中使用 noexcept 规范,那么所有的赌注都将被取消。即使您的编译器在异常离开函数时没有终止程序(例如,出于运行时效率的原因,VS 不会终止程序),您的代码也可能由于优化而无法执行您的想法。例如:
void f() noexcept
{
a();
b();
}
如果a() 实际抛出并且b() 有副作用,则函数行为将无法预测,因为您的编译器可能决定在a() 之前执行b(),因为您已经告诉它不会抛出异常.
编辑:现在是您问题的第二部分:如何使函数不抛出?
首先你需要问问自己你的函数是否真的应该是非抛出的。例如:
class C
{
C* CreateInstance()
{
return new C();
}
}
由于运算符new 可以抛出std::bad_alloc,CreateInstance() 可以抛出。您可以尝试使用 try-catch 块来避免它,处理或吞下任何可能在 try 块内抛出的异常,但这真的明智吗?例如:
C* CreateInstance()
{
try
{
return new C();
}
catch (...)
{
return null;
}
}
问题似乎已解决,但您的调用者是否准备好让CreateInstance() 返回null?如果没有,当他们尝试使用该指针时会发生崩溃。此外,std::bad_alloc 通常意味着您的内存已用完,您只是将问题推迟。
所以要小心:有些函数可以不抛出,但应该允许其他函数抛出。异常安全不是小事。