The standard does not require special optimization in the case of an unnamed exception object. On the contrary, then it requires the effect, as if the temporary was initialized by the copy. This copying can lead to dynamic memory allocation.
N3290 ยง15.3 / 16 :
If a name is specified in the exception declaration, it declares a variable that is initialized with a copy (8.5) of the exception object. If the exception declaration indicates the type of the object but does not indicate the name, the temporary (12.2) is initialized with a copy (8.5) from the exception object. The lifetime of a variable or a temporary one ends after the handler exits after the destruction of any automatic objects initialized in the handler.
The paragraph above does not mention catch by reference, and therefore it can be reasonably concluded that it is applied regardless of whether the exception object is caught by reference; that the copy is built anyway.
However, this contradicts the following paragraph:
N3290 ยง15.3 / 17 :
When a handler declares a mutable object, any changes to this object will not affect the temporary object that was initialized by running the throw statement. When the handler declares a reference to a mutable object, any changes to the referenced object are changes to the initialized temporary object when the throw expression was executed and will have the effect that the object is discarded.
So, the declared type T& (with T not const ) is the only case when C ++ 11 requires a direct reference to an abandoned object instead of copying. And this is also in C ++ 03, except that C ++ 03 contains additional wording about as-if optimization. So, for formal preference should be for
catch( T& name )
and
catch( T& )
However, I have always encountered exceptions such as catch( T const& ) . From a practical point of view, it can be assumed that the compiler optimizes this for direct reference to an abandoned object, even if it is possible to develop cases where the observed program effect will then be non-standard. For example <evil grin>
#include <stdio.h> #include <stdexcept> struct Error : std::runtime_error { public: static Error* pThrown; char const* pMessage_; Error() : std::runtime_error( "Base class message" ) , pMessage_( "Original message." ) { printf( "Default-construction of Error object.\n" ); pThrown = this; } Error( Error const& other ) : std::runtime_error( other ) , pMessage_( other.pMessage_ ) { printf( "Copy-construction of Error obejct.\n" ); } char const* what() const throw() { return pMessage_; } }; Error* Error::pThrown = 0; int main() { printf( "Testing non-const ref:\n" ); try { throw Error(); } catch( Error& x ) { Error::pThrown->pMessage_ = "Modified message."; printf( "%s\n", x.what() ); } printf( "\n" ); printf( "Testing const ref:\n" ); try { throw Error(); } catch( Error const& x ) { Error::pThrown->pMessage_ = "Modified message"; printf( "%s\n", x.what() ); } }
With MinGW g ++ 4.4.1 and Visual C ++ 10.0, the output is & hellip;
Testing non-const ref:
Default-construction of Error object.
Modified message.
Testing const ref:
Default-construction of Error object.
Modified message
A pedantic formalist may say that both compilers are inappropriate, without creating a copy for the Error const& case. A practical practitioner can say hey, what else did you expect? And I say that the wording in the standard here is very far from perfect, and that, if anything, it should be expected that the clarification will explicitly allow the conclusion above, so that catching the const reference is safe and most effective.
Summarizing by. question OP:
Link Capture won & rsquo; t calls the copy constructor, which can potentially terminate program execution.
The standard only guarantees this for reference to non const .
In practice, as shown, it is also guaranteed to reference const , even when program results are then exposed.
Cheers and hth.,