Reputation: 1597
Why throwing exception which is a reference calls copy constructor?
struct Error
{
Error() {}
Error(const Error&) = delete;
};
int main()
{
Error& error = *new Error;
throw error;
}
Compilation error:
error: declared here
Error(const Error&) = delete;
It does not happen when throwing pointer like:
int main()
{
Error* error = new Error;
throw error;
}
This is OK.
Upvotes: 0
Views: 262
Reputation: 677
Before unwinding stack a throw operator (except throw; without an argument, used for rethrowing) creates an exception object (in a special memory area). Depending on circumstances, the object is initialized in different ways: constructor, copy constructor, move constructor (https://en.cppreference.com/w/cpp/language/copy_elision) using what was provided to the throw operator. Providing the reference is ok, but three:
When you pass a reference to Error to the throw operator, the type of the exception object is Error, and we need to initialize an Error exception object in that specific memory area..
When you pass a pointer to Error to a throw operator, the type of the exception object is a pointer to Error (Error *), so the pointer is copied, not the Error object which the pointer points to. The copying pointer to error has nothing to do with calling the copy constructor of Error, so you don’t have the error in that case.
Upvotes: 0
Reputation: 385098
You cannot throw a reference. Throwing always copies the thrown expression value into a special area of storage set aside for thrown objects. Otherwise, you'd almost always be "catching" a dangling reference, as is [theoretically] the case in your code.
Your Error
type cannot be copied, so the program is impossible.
However, a pointer can of course be copied, and the main problem in your final example is a memory leak. Also your program will simply terminate at the throw
statement as you don't have any try
/catch
.
Upvotes: 6