"throw MyException()"和"throw (MyException())"有区别吗?
Is there a difference between "throw MyException()" and "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之前的可选省略(例如GCC中的-fno-elide-constructors
(
如果,正如其他一些人所声称的那样,可能会有这样一件事:;抛出引用";(它变得摇摇欲坠(,你只会看到T
的一个构造。事实上,不存在引用类型的表达式,尽管decltype
和auto
尽了最大努力向你假装存在。
在这两种情况下,我们给throw
的表达式都是右值MyException
当使用推导的返回类型(通过decltype(auto)
(时,我们必须小心return
的原因是推导考虑了值类别。如果你有一个局部变量int x
,那么在return x
中,表达式x
是xvalueint
,所以你推导的类型将是int
,一切都很好。如果您改为编写return (x)
,则表达式为左值int
,这将导致推导出的int&
类型,并且突然出现问题。请注意,这两个表达式都没有引用类型(实际上并不存在(。但无论如何,这些都与throw
场景无关,尤其是因为你的论点最初是暂时的。
我相信它的工作原理类似于C++14及更高版本中的返回语句,括号中表示要抛出的类型是引用,而不是异常实例本身。引用将被存储、复制并像处理异常一样处理,但引用指向的临时对象可能会在堆栈展开过程中被销毁,这可能会导致问题。如果您的异常对象是POD类型,则可能不会立即引起问题,因为在堆栈上创建的此类对象的销毁是微不足道的,但它仍然是未定义的行为。
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- `throw 1` in C++
- gnuradio c++ connect self() throw bad_weak_ptr
- 为什么 c++ 使用 throw() 关键字来指示函数不会引发任何异常
- 是否有任何版本的C++(甚至是试行标准)是"throw()"并不意味着"cannot throw, ever"?
- 实现此"on error, throw"回调的最佳方法是什么?
- 是否有理由大多数/所有 try-catch 示例只对 throw 语句使用 void 子函数
- throw() 函数应该总是在异常时展开堆栈并允许捕获异常还是必须调用 std::terminate ?
- GCC/GCOV 为 使用 throw() / noexexcept 函数生成的不同分支覆盖
- Poco::Net::HTTPClientSession throw exception without unique_
- 防止在将未引发的异常作为参数传递时在"throw e;"中切片
- 模板通过一个专门化同时接受throw和nothrow
- 是否可以从输入流中'throw away'读取值?
- std :: tr1 :: shared_ptr throw bad_alloc,也是一个好主意
- 我是否可以阻止throw调用malloc
- C++03的throw()说明符和C++11的noexcept之间有什么区别
- 为什么"throw MyClass"不起作用,而"throw MyClass()"却行得通?
- C++ sendto() 给出"invalid conversion from ‘int (*)(int, int, int)throw ()’ to ‘int’"错误
- "warning C4987: nonstandard extension used: 'throw (...)'"是什么意思?
- 我该怎么做 throw 来处理 C++ 中的错误数据类型