在函数签名中使用c++ throw关键字被认为是坏习惯的技术原因是什么?
bool some_func() throw(myExc)
{
...
if (problem_occurred)
{
throw myExc("problem occurred");
}
...
}
在函数签名中使用c++ throw关键字被认为是坏习惯的技术原因是什么?
bool some_func() throw(myExc)
{
...
if (problem_occurred)
{
throw myExc("problem occurred");
}
...
}
当前回答
对于只返回成员变量且不可能抛出异常的内联函数的no throw规范可能被某些编译器用于执行悲观化(优化的反义词),这可能会对性能产生不利影响。这在Boost文献中有描述:异常规范
对于一些编译器,如果进行了正确的优化,并且该函数的使用以一种合理的方式影响性能,那么非内联函数的无抛出规范可能是有益的。
对我来说,是否使用它听起来像是一个由非常挑剔的眼睛做出的决定,作为性能优化工作的一部分,可能会使用分析工具。
对于那些赶时间的人,引用以上链接(包含一个简单编译器在内联函数上指定throw的不良意外影响的示例):
Exception-specification rationale Exception specifications [ISO 15.4] are sometimes coded to indicate what exceptions may be thrown, or because the programmer hopes they will improve performance. But consider the following member from a smart pointer: T& operator*() const throw() { return *ptr; } This function calls no other functions; it only manipulates fundamental data types like pointers Therefore, no runtime behavior of the exception-specification can ever be invoked. The function is completely exposed to the compiler; indeed it is declared inline Therefore, a smart compiler can easily deduce that the functions are incapable of throwing exceptions, and make the same optimizations it would have made based on the empty exception-specification. A "dumb" compiler, however, may make all kinds of pessimizations. For example, some compilers turn off inlining if there is an exception-specification. Some compilers add try/catch blocks. Such pessimizations can be a performance disaster which makes the code unusable in practical applications. Although initially appealing, an exception-specification tends to have consequences that require very careful thought to understand. The biggest problem with exception-specifications is that programmers use them as though they have the effect the programmer would like, instead of the effect they actually have. A non-inline function is the one place a "throws nothing" exception-specification may have some benefit with some compilers.
其他回答
好吧,当谷歌关于这个抛出规范,我有一看这篇文章:- (http://blogs.msdn.com/b/larryosterman/archive/2006/03/22/558390.aspx)
我在这里也复制了它的一部分,这样它就可以在未来使用,不管上面的链接是否有效。
class MyClass
{
size_t CalculateFoo()
{
:
:
};
size_t MethodThatCannotThrow() throw()
{
return 100;
};
void ExampleMethod()
{
size_t foo, bar;
try
{
foo = CalculateFoo();
bar = foo * 100;
MethodThatCannotThrow();
printf("bar is %d", bar);
}
catch (...)
{
}
}
};
当编译器看到这一点时,使用"throw()"属性,编译器可以完全优化"bar"变量,因为它知道没有办法从MethodThatCannotThrow()抛出异常。如果没有throw()属性,编译器必须创建“bar”变量,因为如果MethodThatCannotThrow抛出异常,异常处理程序可能/将依赖于bar变量的值。
此外,像prefast这样的源代码分析工具可以(也将)使用throw()注释来提高它们的错误检测能力——例如,如果您有一个try/catch,并且您调用的所有函数都标记为throw(),那么您就不需要try/catch了(是的,如果您稍后调用一个可能抛出的函数,这就有问题了)。
当将throw规范添加到语言中时,它是出于最好的意图,但实践证明了一种更实用的方法。
在c++中,我的一般经验法则是只使用抛出规范来指示一个方法不能抛出。这是一个强有力的保证。否则,假设它可以抛出任何东西。
Jalf已经链接到它了,但是GOTW很好地解释了为什么异常规范没有人们希望的那么有用:
int Gunc() throw(); // will throw nothing (?)
int Hunc() throw(A,B); // can only throw A or B (?)
这些评论正确吗?不完全是。Gunc()可能确实会扔东西,而Hunc()很可能会扔A或B以外的东西!如果它们这样做,编译器只会保证把它们打得毫无意义……哦,大多数情况下,也会把你的程序打得毫无意义。
这就是最终的结果,您可能只会调用terminate(),并且您的程序会快速但痛苦地死亡。
GOTWs的结论是:
因此,以下似乎是我们作为一个社区到目前为止学到的最好的建议: 寓意#1:永远不要编写异常规范。 寓意2:可能除了一个空的,但如果我是你,我甚至会避免这样做。
对于只返回成员变量且不可能抛出异常的内联函数的no throw规范可能被某些编译器用于执行悲观化(优化的反义词),这可能会对性能产生不利影响。这在Boost文献中有描述:异常规范
对于一些编译器,如果进行了正确的优化,并且该函数的使用以一种合理的方式影响性能,那么非内联函数的无抛出规范可能是有益的。
对我来说,是否使用它听起来像是一个由非常挑剔的眼睛做出的决定,作为性能优化工作的一部分,可能会使用分析工具。
对于那些赶时间的人,引用以上链接(包含一个简单编译器在内联函数上指定throw的不良意外影响的示例):
Exception-specification rationale Exception specifications [ISO 15.4] are sometimes coded to indicate what exceptions may be thrown, or because the programmer hopes they will improve performance. But consider the following member from a smart pointer: T& operator*() const throw() { return *ptr; } This function calls no other functions; it only manipulates fundamental data types like pointers Therefore, no runtime behavior of the exception-specification can ever be invoked. The function is completely exposed to the compiler; indeed it is declared inline Therefore, a smart compiler can easily deduce that the functions are incapable of throwing exceptions, and make the same optimizations it would have made based on the empty exception-specification. A "dumb" compiler, however, may make all kinds of pessimizations. For example, some compilers turn off inlining if there is an exception-specification. Some compilers add try/catch blocks. Such pessimizations can be a performance disaster which makes the code unusable in practical applications. Although initially appealing, an exception-specification tends to have consequences that require very careful thought to understand. The biggest problem with exception-specifications is that programmers use them as though they have the effect the programmer would like, instead of the effect they actually have. A non-inline function is the one place a "throws nothing" exception-specification may have some benefit with some compilers.
不,这被认为是不好的做法。相反,它通常被认为是一个坏主意。
http://www.gotw.ca/publications/mill22.htm详细介绍了原因,但问题部分在于编译器无法强制执行,因此必须在运行时进行检查,这通常是不可取的。而且它在任何情况下都没有得到很好的支持。(MSVC忽略异常规范,但throw()除外,它将其解释为保证不会抛出异常。