在实现非抛出交换时我应该使用 throw() 吗?

发布于 2024-10-01 16:53:59 字数 506 浏览 7 评论 0原文

在实现非抛出交换习惯用法时,我应该使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

千纸鹤 2024-10-08 16:53:59

在 C++03 中,你可以把它放在那里,但如果确实没有抛出这些花哨的东西,那么它基本上只是文档。通过添加等效的 try / catch(...) { std::unexpected(); 可能会或可能不会影响性能; } 围绕函数的调用:是否可以在不影响性能的情况下完成此操作取决于实现。

如果您计划在 C++0x 中使用 noexcept 运算符 (5.3.7),那么突然间值得拥有非抛出异常规范,以便运算符给出“正确”答案。我真的不知道 noexcept 运算符的用途,但如果有一个巧妙的通用用途,例如当某些东西不抛出时变得更有效的算法,那么我想它会有必要将函数标记为非抛出,以获得任何好处。

例如:

void foo() noexcept;
void bar();

template <void(*FUNC)()>
void generic_thing() {
    if (noexcept(FUNC()) {
        // this won't throw, perhaps we can somehow take advantage of that
        FUNC();
    } else {
        // this might throw
        FUNC();
    }
}

旧式异常规范(动态异常规范)在 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 the noexcept 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:

void foo() noexcept;
void bar();

template <void(*FUNC)()>
void generic_thing() {
    if (noexcept(FUNC()) {
        // this won't throw, perhaps we can somehow take advantage of that
        FUNC();
    } else {
        // this might throw
        FUNC();
    }
}

Old style exception specifications (dynamic-exception-specification) are deprecated in C++0x (and pointless in C++03).

我纯我任性 2024-10-08 16:53:59

这不是一个好主意,不。原因是标准知道有时不可能强制执行 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 what throw() 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 indeed swap() doesn't throw (and it shouldn't; that's its raison d'être) then specifying noexcept is a good idea.

梦里兽 2024-10-08 16:53:59

事实上,不。异常规范是一个可爱的想法,但现实是它们对大多数代码的阻碍多于帮助。没有人使用它们,并且它们在 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++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文