我想知道编写异常收件箱和发件箱是否会改变特定程序的行为,例如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)
异常对象是复制初始化的 ( 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. 事实上,不存在引用类型表达式这样的东西,尽管他们尽了最大努力decltype并auto假装有。
在这两种情况下,我们给出的表达式throw都是 rvalue MyException。
我们return在使用推导返回类型(via decltype(auto))时必须小心的原因是推导考虑了值类别。如果您有一个局部变量int x,则return x表达式中x为xvalueint,因此您推导出的类型将为int,一切正常。如果您return (x)改为编写,则表达式为lvalueint,这会导致推导类型为 ,int&并且突然出现问题。请注意,这两个表达式都没有引用类型(实际上不存在的东西)。但throw无论如何,这一切都与您的场景无关,尤其是因为您的论点首先是暂时的。
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |