Eu escrevi o código abaixo...
#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) {
}
}
Estou obtendo a seguinte saída no C++17 e versões posteriores...
Constructor called
Copy Constructor called
Até mesmo a elisão de cópia garantida do C++17 diz "Copy elision is mandatory in Throwing and catching exceptions by value"
. Estou obtendo a "Copy Constructor called"
saída as.
Estou esquecendo de alguma coisa?
Honestamente, isso não é obrigatório, veja abaixo, e funciona como esperado - quando
test()
é chamado, um compilador reserva uma memória ondeError
será construído setest()
lançar uma exceção. Até o C++17, ele podia criarError
e copiar para esse armazenamento reservado.A cópia que você observa é feita aqui:
catch (Error e)
-Error
é copiado daquele armazenamento reservado para um argumento local de função. Até o C++17, a saída poderia serSe você não quiser copiar um objeto, corrija-o:
catch (Error &e)
oucatch (const Error &e)
.classe.copy.elision#1.4
O padrão está dizendo que
catch (Error e)
pode ser tratado comocatch (Error &e)
. Observe que pode não é deve .