Reputation: 2975
Referring to http://en.wikipedia.org/wiki/Copy_elision
I run below code:
#include <iostream>
struct C {
C() {}
C(const C&) { std::cout << "Hello World!\n"; }
};
void f() {
C c;
throw c; // copying the named object c into the exception object.
} // It is unclear whether this copy may be elided.
int main() {
try {
f();
}
catch(C c) { // copying the exception object into the temporary in the exception declaration.
} // It is also unclear whether this copy may be elided.
}
The Output I got:
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ make clean
rm -f Trial.exe Trial.o
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ make
g++ -Wall Trial.cpp -o Trial
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ ./Trial
Hello World!
Hello World!
I understand that the compiler might have optimized the code with unnecessary copying, which it is not doing here.
But What I want to ask, How does two calls to the copy constructor
is being made?
catch(C c)
- Since we are passing by value, hence here the copy constructor is being called.
But at throw c
how is copy constructor being called? Can someone explain?
Upvotes: 11
Views: 6315
Reputation: 93
But at throw c how is copy constructor being called? Can someone explain?
C++ exceptions must be copy/move constructable if you want to do throw ex;
as what's happening behind the scene is that the C++ ABI will allocate an exception object (via __cxa_allocate_exception) somewhere and copy/move your exception object, either it's on the heap or stack, before it actually starts the stack unwinding process.
Reference https://blog.the-pans.com/cpp-exception-2/
Upvotes: 0
Reputation: 99
Copy & Move constructor while throwing user-defined type object
struct demo
{
demo() = default;
demo(demo &&) = delete;
demo(const demo &) = delete;
};
int main()
{
throw demo{};
return 0;
}
error: call to deleted constructor of 'demo'
throw demo{};
^~~~~~
note: 'demo' has been explicitly marked deleted here
demo(demo &&) = delete;
^
1 error generated.
compiler exit status 1
From: 7 best practices for exception handling in C++
Upvotes: 0
Reputation: 206526
throw c;
Creates a temporary object and it is this temporary object that is thrown. The creation of the temporary might be through copy/move constructor. And yes this copy/move can be elided.
References:
C++11 15.1 Throwing an exception
§3:
A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type.........
§5:
When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible, even if the copy/move operation is elided (12.8).
Upvotes: 14