By R. Martinho Fernandes


2011-09-13 12:02:01 8 Comments

Consider an exception class with a copy constructor with side-effects.

Can a compiler skip calling the copy constructor here:

try {
    throw ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }

What about this:

try {
    something_that_throws_ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }

(yes, I know this is all very ugly, this was inspired by another question)

3 comments

@Konstantin Oznobihin 2011-09-13 12:21:08

Yes, it can be elided both during throwing and catching. For catching it can be elided only when the type specified in the catch clause is the same (save for cv-qualifications) as the type of the exception object. For more formal and detailed description see C++11 12.8/31.

...This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

...

  • in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

...

  • when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy/move operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration.

@Matthieu M. 2011-09-13 12:24:20

Interesting, though the quote is quite narrow... so it's difficult to be sure it actually refers to this particular situation.

@Konstantin Oznobihin 2011-09-13 12:37:13

@Mattieu: I was a bit lazy about adding all relevant quotations, anyhow, here it is.

@Matthieu M. 2011-09-13 12:43:09

+1 then, here it's clear that it is allowed.

@R. Martinho Fernandes 2011-09-13 13:44:11

Thanks for the quotes that leave no doubts :)

@Steve Jessop 2011-09-13 12:22:44

I think this is specifically permitted. For C++03, 15.1/3 says:

A throw-expression initializes a temporary object, called the exception object,

and 12/15 says:

when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the tempo- rary object directly into the target of the omitted copy

So, the secret hiding place where in-flight exceptions are kept, is defined by the standard to be a temporary, and hence is valid for copy-elision.

Edit: oops, I've now read further. 15.1/5:

If the use of the temporary object can be eliminated without changing the meaning of the program except for the execution of constructors and destructors associated with the use of the temporary object (12.2), then the exception in the handler can be initialized directly with the argument of the throw expression.

Doesn't get much clearer.

Whether it actually will... if the catch clause were to re-raise the exception (including if it called non-visible code that might do so), then the implementation needs that "temporary object called the exception object" still to be around. So there might be some restrictions on when that copy elision is possible. Clearly an empty catch clause can't re-raise it, though.

@Nawaz 2011-09-13 12:11:14

Yes. If the catch catches the exception by reference, then there will not be copy (well, that is by definition).

But I think that is not your question, and I believe the code which you've written is written on purpose with no mention of reference. If that is the case, then yes, even in this case, copy can be elided. Actually initialization of the variable in the catch is direct-initialization in theory. And copy in a direct-initialization can be elided by the compiler where it's possible.

C++03 ยง8.5/14 reads,

[...] In certain cases, an implementation is permitted to eliminate the copying inherent in this direct-initialization by constructing the intermediate result directly into the object being initialized;

@Matthieu M. 2011-09-13 12:16:26

There is no reference here, only copy elision when catching by value is considered.

@Nawaz 2011-09-13 12:18:56

@Matthieu: Most part of my answer addresses that. I think you read only the first sentence?

@Matthieu M. 2011-09-13 12:20:26

Regarding the standard quote: it is unclear whether it concerns copy elision in general or is only about catch, could you precise ?

@Matthieu M. 2011-09-13 12:21:09

I didn't read only the first sentence, the rest of the answer is actually interesting... but why begin with something the OP did not ask ?

@Nawaz 2011-09-13 12:22:53

@Matthieu: It may be he wants to avoid copy, but doesn't know how to, that is why I wrote the first sentence. :D

Related Questions

Sponsored Content

5 Answered Questions

[SOLVED] Catch multiple exceptions in one line (except block)

36 Answered Questions

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

8 Answered Questions

[SOLVED] When should I really use noexcept?

25 Answered Questions

[SOLVED] How can I safely create a nested directory?

28 Answered Questions

[SOLVED] Catch multiple exceptions at once?

24 Answered Questions

[SOLVED] Image Processing: Algorithm Improvement for 'Coca-Cola Can' Recognition

10 Answered Questions

4 Answered Questions

[SOLVED] What are copy elision and return value optimization?

5 Answered Questions

[SOLVED] What is the copy-and-swap idiom?

Sponsored Content