I have written the below code...
#include <iostream>
using namespace std;
struct Error {
Error() { cout << "Constructor called\n"; }
Error(const Error&) { cout << "Copy Constructor called\n"; }
};
void test() {
throw Error();
}
int main() {
try {
test();
}
catch (Error e) {
}
}
I am getting the following output on C++17 and later...
Constructor called
Copy Constructor called
Even the C++17 Guaranteed copy elision says "Copy elision is mandatory in Throwing and catching exceptions by value"
. I am getting the "Copy Constructor called"
as output.
Am I missing something?
I have written the below code...
#include <iostream>
using namespace std;
struct Error {
Error() { cout << "Constructor called\n"; }
Error(const Error&) { cout << "Copy Constructor called\n"; }
};
void test() {
throw Error();
}
int main() {
try {
test();
}
catch (Error e) {
}
}
I am getting the following output on C++17 and later...
Constructor called
Copy Constructor called
Even the C++17 Guaranteed copy elision says "Copy elision is mandatory in Throwing and catching exceptions by value"
. I am getting the "Copy Constructor called"
as output.
Am I missing something?
Share Improve this question edited yesterday NJMR asked yesterday NJMRNJMR 1,9641 gold badge28 silver badges50 bronze badges 4 |1 Answer
Reset to default 7Copy elision is mandatory in Throwing and catching exceptions by value
Honestly, this is not mandatory, see below, and this works as expected - when test()
is called, a compiler reserves a memory where Error
will be constructed if test()
throws an exception. Until C++17, it could create Error
and copy it to that reserved storage.
The copy, that you observe, is done here: catch (Error e)
- Error
is copied from that reserved storage to a function local argument. Until C++17, the output could be
Constructor called
Copy Constructor called
Copy Constructor called
If you don't want to copy an object, fix it: catch (Error &e)
or catch (const Error &e)
.
#include <iostream>
struct Error {
Error() { std::cout << "Constructor called\n"; }
Error(const Error &) { std::cout << "Copy Constructor called\n"; }
};
void test() { throw Error(); }
int main() {
try {
test();
} catch (const Error &e) {
}
}
// Output since C++17:
// Constructor called
//
// Possible output until C++17:
// Constructor called
// Copy Constructor called
class.copy.elision#1.4
the copy-initialization of
o
can be omitted by treating the exception-declaration as an alias
The standard is saying that catch (Error e)
can be treated as catch (Error &e)
. Note, can is not must.
error: use of undeclared identifier 'cout'
. – 3CxEZiVlQ Commented yesterdayconst&
: E.15: Throw by value, catch exceptions from a hierarchy by reference – Pepijn Kramer Commented 23 hours ago