Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a difference between "throw MyException()" and "throw (MyException())"?

Tags:

c++

exception

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;
}
like image 415
Ali-Baba Avatar asked Nov 11 '20 17:11

Ali-Baba


People also ask

What is the difference between throw and throw exception?

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.

What is the difference between the throw and throws keyword?

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.

What is the difference between throw throws and throwable in Java?

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.

What is the difference between throw and throw ex in dotnet?

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.


1 Answers

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.

like image 60
Asteroids With Wings Avatar answered Nov 15 '22 01:11

Asteroids With Wings