c++ - “throw MyException()”和“throw (MyException())”有区别吗?
问题描述
我想知道编写异常收件箱和发件箱是否会改变特定程序的行为,例如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;
}
解决方案
异常对象是复制初始化的(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&) {}
}
即使您切换throw T()
到throw (T())
语义(和输出)完全相同:
T()
T(T&&)
~T()
~T()
也就是说,T()
构造一个临时对象,然后将其移入真正的异常对象(存在于某个神奇的“安全空间”中),最终两者都被破坏。
请注意,要查看此证明,您必须返回到 C++14(因为 C++17 在需要真正的异常对象之前不会实现该临时对象,根据所谓的“强制省略”)并转向关闭 C++17 之前的可选省略(例如-fno-elide-constructors
在 GCC 中)。
如果像其他一些人声称的那样,可能存在“抛出引用”(变得悬空)这样的事情,那么您只会看到T
. 事实上,没有引用类型的表达式这种东西,尽管尽了最大的努力decltype
并向auto
你假装有。
在这两种情况下,我们给出的表达式throw
都是 rvalue MyException
。
return
使用推导返回类型(通过)时我们必须小心的原因decltype(auto)
是推导考虑了值类别。如果你有一个局部变量int x
,那么在return x
表达式x
中是xvalueint
,所以你推导的类型将是int
并且一切都很好。如果你改写return (x)
,那么表达式是lvalueint
,这会导致推导类型 of int&
,突然你就会遇到问题。请注意,这两个表达式都没有引用类型(实际上不存在的东西)。但是throw
无论如何,这些都与您的场景无关,尤其是因为您的论点首先是暂时的。
推荐阅读
- python - Amazon MWAA 和 ec2 实例之间的 SSH 连接
- linux - 亚马逊工作区实例上的 sudo yum 更新错误
- linux-kernel - dev_alloc_skb 返回 null
- flutter - 从外部状态范围强制 navDrawer 状态更新
- sharedpreferences - AndroidX Preferences 不会自动从 SharedPreferences 文件中加载保存的值
- sql - 需要在 SQL 中将多行中的列值组合成单行
- javascript - csrf 令牌正在改变不应该改变的地方
- visual-studio-code - 当在 Vs 代码中运行代码时,这总是出现在我的谷歌控制台上
- windows - 在条码扫描事件窗口 10 上触发 Powershell 程序
- java - 在firestore中使用多个字段的查询