C++: Throwing an exception invokes the copy constructor?

后端 未结 6 1120
半阙折子戏
半阙折子戏 2021-01-07 14:02

We have an custom error class that is used whenever we throw an exception:

class AFX_CLASS_EXPORT CCLAError : public CObject

It has the fol

相关标签:
6条回答
  • 2021-01-07 14:34

    The language specification allows the compilers to make as many copies of the original object as they want. There is no restriction on the number of copies.

    That means, your custom exception class must have an accessible copy-constructor, either the compiler generated one, or user-defined one.

    0 讨论(0)
  • 2021-01-07 14:40

    Several points:

    1st of all don't call throw new foo() use throw foo

    2nd when your write:

    catch(foo const &e) {
       throw e;
    }
    

    You actually create a new exception, and if for example the exception that was thrown is subclass of foo they my calling throw e you would loose this information and actually use a copy constructor to generate foo from e - whatever it was.

    Now when you call

    catch(foo const &e) {
       throw;
    }
    

    You don't create a new exception but rather propagate the same exception.

    So: never use throw e; to propagate the exception forward, use throw;

    0 讨论(0)
  • 2021-01-07 14:43

    It appears that you have misunderstood what re-throw means. When you do -

    catch(CCLAError& e)
    {
       throw e;
    }
    

    -- you are NOT rethrowing. Instead, as you have observed, you are indeed creating a copy of the new exception. Instead (again, as you have found for yourself), this is what is technically the correct way to re-throw:

    catch(CCLAError& e)
    {
       throw;
    }
    

    Read chapter 14 in Stroustrup's TC++PL (14.3.1 deals with rethrowing).

    Also, you do NOT have to do -

    throw new CCLAError( ... )
    

    Instead, do -

    throw CCLAError( ... )
    

    -- like you were doing before, only receive by CONST reference (you cannot hold a reference to a temporary).

    catch(const CCLAError &e)
    
    0 讨论(0)
  • 2021-01-07 14:46

    When you throw an exception, the object you're throwing generally resides on the stack. The stack is getting cleaned up as part of the process of throwing, so the compiler must make a copy that can continue to live beyond that point.

    When you throw an object with new, you're not throwing the actual object but you're throwing a pointer to the object. That means your catch block must also catch a pointer rather than a reference. Don't forget to delete the pointer or you'll have a memory leak!

    When the catch block uses throw; instead of throw e; it can reuse the copy it made earlier and there's no need to make another copy.

    0 讨论(0)
  • 2021-01-07 14:56

    The type of the object thrown must be copyable because the throw expression may make a copy of its argument (the copy may be elided or in C++11 a move may take place instead, but the copy constructor must still be accessible and callable).

    Rethrowing the exception using throw; will not create any copies. Throwing the caught exception object using throw e; will cause a copy of e to be made. This is not the same as rethrowing the exception.

    Your "updated" code does not work as you expect. catch (CCLAError&) will not catch an exception of type CCLAError*, which is the type of the exception thrown by throw new CCLAError(...);. You would need to catch CCLAError*. Do not do this, though. Throw exceptions by value and catch by reference. All exception types should be copyable.

    0 讨论(0)
  • 2021-01-07 14:56

    However, I do not understand why re-throwing a caught exception would invoke the copy constructor.

    It doesn't, but re-throwing the thrown exception is done with throw;. When you do throw e; you are requesting to throw a copy of the caught exception.

    0 讨论(0)
提交回复
热议问题