When certain criteria are met, an implementation is
allowed to omit the copy/move construction of a class object,
even if the constructor selected for the copy/move operation and/or the
destructor for the object have
side effects
. In such cases, the
implementation treats the source and target of the
omitted copy/move operation as simply two different ways of
referring to the same object
. If the first parameter of the
selected constructor is an rvalue reference to the object's type,
the destruction of that object occurs when the target would have been destroyed;
otherwise, the destruction occurs at the later of the times when the
two objects would have been destroyed without the
optimization
.
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 return statement in a function with a class return type,
when the expression is the name of a non-volatile
object with automatic storage duration (other than a function parameter or a variable
introduced by the exception-declaration of a
handler ([except.handle]))
with the same type (ignoring cv-qualification) as
the function return type, the copy/move operation can be
omitted by constructing the object directly
into the function call's return object
- in a throw-expression ([expr.throw]), when the operand
is the name of a non-volatile object with automatic storage duration
(other than a function or catch-clause parameter)
that belongs to a scope that does not contain
the innermost enclosing compound-statement
associated with a try-block (if there is one),
the copy/move operation can be omitted by
constructing the object directly into the exception object
- in a coroutine, a copy of a coroutine parameter
can be omitted and references to that copy replaced with references to the
corresponding parameter if the meaning of the program will be unchanged except for
the execution of a constructor and destructor for the parameter copy object
- when the exception-declaration of a
handler ([except.handle]) declares an object of the same
type (except for cv-qualification) as the exception
object ([except.throw]), the copy 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.
[
Note 1:
There cannot be a move from the exception object because it is
always an lvalue
. —
end note]
Copy elision is not permitted
where an expression is evaluated in a context
requiring a constant expression (
[expr.const])
and in constant initialization (
[basic.start.static])
. [
Note 2:
It is possible that copy elision is performed
if the same expression
is evaluated in another context
. —
end note]