“throw MyException()”和“throw (MyException())”之间有区别吗?

Ali*_*aba 7 c++ exception

我想知道编写异常收件箱和发件箱是否会改变特定程序的行为,例如throw MyException(); 抛出(MyException());

我的代码:

#include <iostream>
#include <exception>
using namespace std;

class MyException: public exception {
public:
      virtual const char* what() const throw()
      {
         return "Something bad happened";
      }
};
class Test
{
public:
   void goWrong()
   {
      throw (MyException());
   }
};

int main()
{
   Test test;
   try
   {
      test.goWrong();
   }
   catch (MyException &err)
   {
      cout << "The Exception is Executed: " << err.what() << '\n';
   }
   cout << "Still Running" << '\n';
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ast*_*ngs 6

异常对象是复制初始化的 ( except.throw/3),所以你使用哪一个并不重要;结果是一样的。

即使你从中得到了一个引用限定符,复制初始化也会忽略它。

我们可以用一些跟踪输出来证明这一点:

#include <cstdio>
using std::printf;

struct T
{
    T() { printf("T()\n"); }
    ~T() { printf("~T()\n"); }
    T(const T&) { printf("T(const T&)\n"); }
    T(T&&) { printf("T(T&&)\n"); }
    T& operator=(const T&) { printf("T& operator=(const T&)\n"); return *this; }
    T& operator=(const T&&) { printf("T& operator=(T&&)\n"); return *this; }
};

int main()
{
    try
    {
        throw T();
    }
    catch (const T&) {}
}
Run Code Online (Sandbox Code Playgroud)

即使你切换throw T()throw (T())语义(和输出)也完全一样:

T()
T(T&&)
~T()
~T()
Run Code Online (Sandbox Code Playgroud)

也就是说,T()构造了一个临时对象,然后移入真正的异常对象(存在于某个神奇的“安全空间”中),最终两者都被销毁。

请注意,要查看此证明,您必须返回 C++14(因为 C++17 不会在需要真正的异常对象之前实现该临时对象,即所谓的“强制省略”)并转关闭 pre-C++17 可选省略(例如-fno-elide-constructors在 GCC 中)。

如果像其他一些人声称的那样,可能存在诸如“抛出引用”之类的事情(变得悬空),那么您只会看到T. 事实上,不存在引用类型表达式这样的东西,尽管他们尽了最大努力decltypeauto假装有。

在这两种情况下,我们给出的表达式throw都是 rvalue MyException

我们return在使用推导返回类型(via decltype(auto))时必须小心的原因是推导考虑了值类别。如果您有一个局部变量int x,则return x表达式中xxvalueint,因此您推导出的类型将为int,一切正常。如果您return (x)改为编写,则表达式为lvalueint,这会导致推导类型为 ,int&并且突然出现问题。请注意,这两个表达式都没有引用类型实际上不存在的东西)。但throw无论如何,这一切都与您的场景无关,尤其是因为您的论点首先是暂时的。

  • @阿里巴巴是的,但我不知道_为什么_你想将异常对象放在括号内;没有其他人这样做。 (2认同)