在实现非抛出交换时我应该使用 throw() 吗?
在实现非抛出交换习惯用法时,我应该使用 throw() 吗?
namespace A
{
struct B
{
void swap( B& other ) throw()
{ /* fancy stuff that doesn't throw */ }
};
void swap( B& lhs, B& rhs ) throw()
{ lhs.swap(rhs); }
}
namespace std
{
template<>
void swap( A::B& lhs, A::B& rhs ) throw()
{ lhs.swap(rhs); }
}
我特别担心将 throw()
规范放在 std::swap
的专门化上。
额外问题:
使用 C++0x 的 noexcept
关键字时,答案是否不同?
When implementing the non-throwing swap idiom, should I use throw()
?
namespace A
{
struct B
{
void swap( B& other ) throw()
{ /* fancy stuff that doesn't throw */ }
};
void swap( B& lhs, B& rhs ) throw()
{ lhs.swap(rhs); }
}
namespace std
{
template<>
void swap( A::B& lhs, A::B& rhs ) throw()
{ lhs.swap(rhs); }
}
In particular I worry about putting the throw()
specification on the specialization of std::swap
.
Bonus question:
Is the answer different when using C++0x's noexcept
keyword?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 C++03 中,你可以把它放在那里,但如果确实没有抛出这些花哨的东西,那么它基本上只是文档。通过添加等效的 try / catch(...) { std::unexpected(); 可能会或可能不会影响性能; } 围绕函数的调用:是否可以在不影响性能的情况下完成此操作取决于实现。
如果您计划在 C++0x 中使用
noexcept
运算符 (5.3.7),那么突然间值得拥有非抛出异常规范,以便运算符给出“正确”答案。我真的不知道 noexcept 运算符的用途,但如果有一个巧妙的通用用途,例如当某些东西不抛出时变得更有效的算法,那么我想它会有必要将函数标记为非抛出,以获得任何好处。例如:
旧式异常规范(动态异常规范)在 C++0x 中已弃用(在 C++03 中毫无意义)。
In C++03 you can put it there, but if it's true that the fancy stuff doesn't throw, it's basically just documentation. It may or may not affect performance by adding the equivalent of
try / catch(...) { std::unexpected(); }
around calls to the function: it's up to the implementation whether it can do it without affecting performance.If you're planning to use the
noexcept
operator (5.3.7) in C++0x, then suddenly it becomes worth having non-throwing exception specifications, so that the operator gives the "right" answer. I don't really know what thenoexcept
operator is for, but if there's a clever generic use for it, for example algorithms that become more efficient when something is non-throwing, then I guess it's going to become necessary to mark functions as non-throwing, to get whatever the benefit is.For example:
Old style exception specifications (dynamic-exception-specification) are deprecated in C++0x (and pointless in C++03).
这不是一个好主意,不。原因是标准知道有时不可能强制执行 throw() 的正确性,而这正是引入 throw() 的首要目的。特别是,在模板的情况下,根据实例化可能会或可能不会引发异常,如果没有模板实例化,就不可能检查正确性。因此,该标准甚至不需要编译器强制执行异常说明符;事实上,它禁止实现拒绝表达式“仅仅因为在执行时它抛出或可能抛出包含函数不允许的异常”(15.4/11)。
如果
throw()
除了文档之外没有任何作用,那么应该将其注释掉;这样至少不会造成误导人类观察者的风险。noexcept
的情况完全不同。noexcept
的出现有不同的原因;性能。如果您可以保证编译器不会抛出异常,那么编译器将允许自己执行一些优化。但是您必须自己进行检查。因此,如果swap()
确实不会抛出异常(而且它不应该;这就是它存在的理由),那么指定noexcept
是一个好主意。It's not a good idea, no. The reason is that the standard knows that at times it's impossible to enforce the
throw()
correctness, which is whatthrow()
was brought in for in the first place. In particular, in the case of templates where an exception may or may not be thrown depending on the instantiation it's impossible to check for correctness without the template instantiation. The standard therefore doesn't even require compilers to enforce the exception specifier; in fact, it forbids an implementation from rejecting an expression "merely because when executed it throws or might throw an exception that the containing function does not allow" (15.4/11).If
throw()
has no effect other than documentation then it should be commented out; this way at least it doesn't pose a risk of misleading the human observer.The case with
noexcept
is wholly different.noexcept
comes to be for a different reason; that of performance. If you can guarantee the compiler no exception is thrown then the compiler allows itself to perform some optimizations. But you will have to do the checks yourself. So, if indeedswap()
doesn't throw (and it shouldn't; that's its raison d'être) then specifyingnoexcept
is a good idea.事实上,不。异常规范是一个可爱的想法,但现实是它们对大多数代码的阻碍多于帮助。没有人使用它们,并且它们在 C++0x 中已被弃用。不要花时间用现代 C++ 编写异常规范。
Realistically, no. Exception specifications were a lovely idea, but the reality of them was that they hindered more than helped the majority of code. Nobody uses them and they're deprecated in C++0x. Don't spend time writing exception specifications in modern C++.