I want to know if writing exceptions inbox and out box is changing the behavior or not of a particular program, for example throw MyException(); and throw (MyException());
My Code:
#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;
}
The throw keyword is used to throw an exception explicitly. It can throw only one exception at a time. The throws keyword can be used to declare multiple exceptions, separated by a comma. Whichever exception occurs, if matched with the declared ones, is thrown automatically then.
The throws keyword is used to declare which exceptions can be thrown from a method, while the throw keyword is used to explicitly throw an exception within a method or block of code.
Sr. no. 1. Java throw keyword is used throw an exception explicitly in the code, inside the function or the block of code. Java throws keyword is used in the method signature to declare an exception which might be thrown by the function while the execution of the code.
throw is used to throw current exception while throw(ex) mostly used to create a wrapper of exception. throw(ex) will reset your stack trace so error will appear from the line where throw(ex) written while throw does not reset stack trace and you will get information about original exception.
The exception object is copy-initialised (except.throw/3
), so it doesn't really matter which one you use; the result is the same.
Copy-initialising would ignore a reference qualifier even if you got one out of this.
We can prove this with some trace output:
#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&) {}
}
Even if you switch from throw T()
to throw (T())
the semantics (and output) are exactly the same:
T()
T(T&&)
~T()
~T()
That is, a temporary T()
is constructed, then moved into the real exception object (which exists in some magical "safe space"), and ultimately both are destructed.
Note that, to see this proof, you do have to go back to C++14 (as C++17 doesn't materialise that temporary until the real exception object is needed, per so-called "mandatory elision") and turn off pre-C++17 optional elision (e.g. -fno-elide-constructors
in GCC).
If, as some others have claimed, there could be such a thing as "throwing a reference" (which became dangling), you'd only ever see one construction of T
. In truth, there is no such thing as expressions of reference type, despite the best efforts of decltype
and auto
to pretend to you that there are.
In both cases, the expression we give to throw
is an rvalue MyException
.
The reason we have to be careful with return
when using a deduced return type (via decltype(auto)
), is that deduction considers value category. If you have a local variable int x
, then in return x
the expression x
is xvalue int
, so your deduced type will be int
and everything is fine. If you write return (x)
instead then the expression is lvalue int
, which results in a deduced type of int&
and suddenly you have problems. Notice that neither expression has reference type (a thing which effectively does not exist). But exactly none of this is relevant in your throw
scenario anyway, not least of all because your argument is a temporary in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With