[class.temporary]

# 6 Basics [[basic]](./#basic)

## 6.8 Memory and objects [[basic.memobj]](basic.memobj#class.temporary)

### 6.8.7 Temporary objects [class.temporary]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4614)

A [*temporary object*](#def:object,temporary "6.8.7 Temporary objects [class.temporary]") is an object created

- [(1.1)](#1.1)

when a prvalue is converted to an xvalue ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) and

- [(1.2)](#1.2)

when needed by the implementation to pass or return an object of suitable type (see below)[.](#1.sentence-1)

Even when the creation of the temporary object is
unevaluated ([[expr.context]](expr.context "7.2.3 Context dependence")),
all the semantic restrictions shall be respected as if the temporary object
had been created and later destroyed[.](#1.sentence-2)

[*Note [1](#note-1)*:

This includes accessibility ([[class.access]](class.access "11.8 Member access control")) and whether it is deleted,
for the constructor selected and for the destructor[.](#1.sentence-3)

However, in the special
case of the operand of a[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")), no temporary is introduced,
so the foregoing does not apply to such a prvalue[.](#1.sentence-4)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4638)

The materialization of a temporary object is generally
delayed as long as possible
in order to avoid creating unnecessary temporary objects[.](#2.sentence-1)

[*Note [2](#note-2)*:

Temporary objects are materialized:

- [(2.1)](#2.1)

when binding a reference to a prvalue ([[dcl.init.ref]](dcl.init.ref "9.5.4 References"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")),

- [(2.2)](#2.2)

when performing certain member accesses on a class prvalue ([[expr.ref]](expr.ref "7.6.1.5 Class member access"), [[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-to-member operators")),

- [(2.3)](#2.3)

when invoking an implicit object member function on a class prvalue ([[expr.call]](expr.call "7.6.1.3 Function call")),

- [(2.4)](#2.4)

when performing an array-to-pointer conversion or subscripting on an array prvalue ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion"), [[expr.sub]](expr.sub "7.6.1.2 Subscripting")),

- [(2.5)](#2.5)

when initializing an object of type std​::​initializer_list<T> from a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")),

- [(2.6)](#2.6)

for certain unevaluated operands ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification"), [[expr.sizeof]](expr.sizeof "7.6.2.5 Sizeof")), and

- [(2.7)](#2.7)

when a prvalue that has type other than cv void appears as a discarded-value expression ([[expr.context]](expr.context "7.2.3 Context dependence"))[.](#2.sentence-2)

â *end note*]

[*Example [1](#example-1)*:

Consider the following code:class X {public: X(int);
 X(const X&);
 X& operator=(const X&); ~X();};

class Y {public: Y(int);
 Y(Y&&); ~Y();};

X f(X);
Y g(Y);

void h() { X a(1);
 X b = f(X(2));
 Y c = g(Y(3));
 a = f(a);}

X(2) is constructed in the space used to hold f()'s argument andY(3) is constructed in the space used to hold g()'s argument[.](#2.sentence-4)

Likewise,f()'s result is constructed directly in b andg()'s result is constructed directly in c[.](#2.sentence-5)

On the other hand, the expressiona = f(a) requires a temporary for
the result of f(a),
which is materialized so that the reference parameter
of X​::​operator=(const X&) can bind to it[.](#2.sentence-6)

â *end example*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4706)

When an object of class type X is passed to or returned from a potentially-evaluated function call,
if X is

- [(3.1)](#3.1)

a scalar type or

- [(3.2)](#3.2)

a class type that
has at least one eligible copy or move constructor ([[special]](special "11.4.4 Special member functions")),
where each such constructor is trivial,
and the destructor of X is either trivial or deleted,

implementations are permitted
to create temporary objects
to hold the function parameter or result object,
as follows:

- [(3.3)](#3.3)

  The first such temporary object
is constructed from the function argument or return value, respectively[.](#3.3.sentence-1)

- [(3.4)](#3.4)

  Each successive temporary object
is initialized from the previous one
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#3.4.sentence-1)

- [(3.5)](#3.5)

  The function parameter or return object is initialized
from the final temporary
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#3.5.sentence-1)

(In all cases, the eligible constructor is used
even if that constructor is inaccessible
or would not be selected by overload resolution
to perform a copy or move of the object)[.](#3.sentence-2)

[*Note [3](#note-3)*:

This latitude is granted to allow objects
to be passed to or returned from functions in registers[.](#3.sentence-3)

â *end note*]

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4747)

Temporary objects are destroyed as the last step
in evaluating
the full-expression ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))
that (lexically) contains the point where
they were created[.](#4.sentence-1)

This is true even if that evaluation ends in throwing an exception[.](#4.sentence-2)

Thevalue computations andside effects of destroying a temporary object
are associated only with the full-expression, not with any specific
subexpression[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4765)

There are several contexts in which temporaries are destroyed at a different
point than the end of the full-expression[.](#5.sentence-1)

The first context is when a default constructor is called to initialize
an element of an array with no corresponding initializer ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#5.sentence-2)

The second context is when a copy constructor is called to copy an element of
an array while the entire array is copied ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"))[.](#5.sentence-3)

In either case, if the constructor has one or more default arguments,
the destruction of every temporary created in a default argument is
sequenced before the construction of the next array element, if any[.](#5.sentence-4)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4778)

The third context is when a reference binds to a temporary object[.](#6.sentence-1)[25](#footnote-25 "The same rules apply to initialization of an initializer_­list object ([dcl.init.list]) with its underlying temporary array.")

The temporary object to which the reference is bound or the temporary object
that is the complete object of a subobject to which the reference is bound
persists for the lifetime of the reference if the glvalue
to which the reference is bound
was obtained through one of the following:

- [(6.1)](#6.1)

a temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")),

- [(6.2)](#6.2)

( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") ),
 where [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is one of these expressions,

- [(6.3)](#6.3)

subscripting ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")) of an array operand,
 where that operand is one of these expressions,

- [(6.4)](#6.4)

a class member access ([[expr.ref]](expr.ref "7.6.1.5 Class member access")) using the . operator
 where the left operand is one of these expressions and
 the right operand designates a non-static data member of non-reference type,

- [(6.5)](#6.5)

a pointer-to-member operation ([[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-to-member operators")) using the .* operator
 where the left operand is one of these expressions and
 the right operand is a pointer to data member of non-reference type,

- [(6.6)](#6.6)

a
  * [(6.6.1)](#6.6.1)

const_cast ([[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")),

  * [(6.6.2)](#6.6.2)

static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")),

  * [(6.6.3)](#6.6.3)

dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")), or

  * [(6.6.4)](#6.6.4)

reinterpret_cast ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"))

converting, without a user-defined conversion,
 a glvalue operand that is one of these expressions
 to a glvalue that refers
 to the object designated by the operand, or
 to its complete object or a subobject thereof,

- [(6.7)](#6.7)

a conditional expression ([[expr.cond]](expr.cond "7.6.16 Conditional operator")) that is a glvalue
 where the second or third operand is one of these expressions, or

- [(6.8)](#6.8)

a comma expression ([[expr.comma]](expr.comma "7.6.20 Comma operator")) that is a glvalue
 where the right operand is one of these expressions[.](#6.sentence-2)

[*Example [2](#example-2)*: template<typename T> using id = T;

int i = 1;int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as aconst int& b = static_cast<const int&>(0); // temporary int has same lifetime as bint&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended â *end example*]

[*Note [4](#note-4)*:

An explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))
is interpreted as
a sequence of elementary casts,
covered above[.](#6.sentence-3)

[*Example [3](#example-3)*: const int& x = (const int&)1; // temporary for value 1 has same lifetime as x â *end example*]

â *end note*]

[*Note [5](#note-5)*:

If a temporary object has a reference member initialized by another temporary object,
lifetime extension applies recursively to such a member's initializer[.](#6.sentence-4)

[*Example [4](#example-4)*: struct S {const int& m;};const S& s = S{1}; // both S and int temporaries have lifetime of s â *end example*]

â *end note*]

The exceptions to this lifetime rule are:

- [(6.9)](#6.9)

  A temporary object bound to a reference parameter in a function call ([[expr.call]](expr.call "7.6.1.3 Function call"))
persists until the completion of the full-expression containing the call[.](#6.9.sentence-1)

- [(6.10)](#6.10)

  A temporary object bound to a reference element of
an aggregate of class type initialized from
a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") ([[dcl.init]](dcl.init "9.5 Initializers"))
persists until the completion of the full-expression
containing the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")[.](#6.10.sentence-1)

- [(6.11)](#6.11)

  A temporary bound to a reference in a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")) persists until the completion of the full-expression containing the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")[.](#6.11.sentence-1)
  [*Note [6](#note-6)*:
  This might introduce a dangling reference[.](#6.11.sentence-2)
 â *end note*]
  [*Example [5](#example-5)*: struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} }; // creates dangling reference â *end example*]

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4886)

The fourth context is when a temporary object
is created in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") of
either a range-based for statement
or an enumerating expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion statements"))[.](#7.sentence-1)

If such a temporary object would otherwise be destroyed
at the end of the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") full-expression,
the object persists for the lifetime of the reference
initialized by the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]")[.](#7.sentence-2)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4896)

The fifth context is when a temporary object is created
in the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") of an iterating or destructuring expansion statement[.](#8.sentence-1)

If such a temporary object would otherwise be destroyed
at the end of that [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]"),
the object persists for the lifetime of the reference
initialized by the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]"), if any[.](#8.sentence-2)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4905)

The sixth context is when a temporary object
is created in a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))[.](#9.sentence-1)

Any temporary objects introduced by
the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")*s* for the variables
with unique names
are destroyed at the end of the structured binding declaration[.](#9.sentence-2)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4913)

Let x and y each be either
a temporary object whose lifetime is not extended, or
a function parameter[.](#10.sentence-1)

If the lifetimes of x and y end at
the end of the same full-expression, andx is initialized before y, then
the destruction of y is sequenced before that of x[.](#10.sentence-2)

If the lifetime of two or more temporaries
with lifetimes extending beyond the full-expressions in which they were created
ends at the same point,
these temporaries are destroyed at that point in the reverse order of the
completion of their construction[.](#10.sentence-3)

In addition, the destruction of such temporaries shall
take into account the ordering of destruction of objects with static, thread, or
automatic storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration"), [[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"), [[basic.stc.auto]](basic.stc.auto "6.8.6.4 Automatic storage duration"));
that is, ifobj1 is an object with the same storage duration as the temporary and
created before the temporary is created
the temporary shall be destroyed beforeobj1 is destroyed;
ifobj2 is an object with the same storage duration as the temporary and
created after the temporary is created
the temporary shall be destroyed afterobj2 is destroyed[.](#10.sentence-4)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4944)

[*Example [6](#example-6)*: struct S { S();
 S(int); friend S operator+(const S&, const S&); ~S();};
S obj1;const S& cr = S(16)+S(23);
S obj2;

The expressionS(16) + S(23) creates three temporaries:
a first temporaryT1 to hold the result of the expressionS(16),
a second temporaryT2 to hold the result of the expressionS(23),
and a third temporaryT3 to hold the result of the addition of these two expressions[.](#11.sentence-1)

The temporaryT3 is then bound to the referencecr[.](#11.sentence-2)

It is unspecified whetherT1 orT2 is created first[.](#11.sentence-3)

On an implementation whereT1 is created beforeT2,T2 shall be destroyed beforeT1[.](#11.sentence-4)

The temporariesT1 andT2 are bound to the reference parameters ofoperator+;
these temporaries are destroyed at the end of the full-expression
containing the call tooperator+[.](#11.sentence-5)

The temporaryT3 bound to the referencecr is destroyed at the end ofcr's
lifetime, that is, at the end of the program[.](#11.sentence-6)

In addition, the order in whichT3 is destroyed takes into account the destruction order of other objects with
static storage duration[.](#11.sentence-7)

That is, becauseobj1 is constructed beforeT3,
andT3 is constructed beforeobj2,obj2 shall be destroyed beforeT3,
andT3 shall be destroyed beforeobj1[.](#11.sentence-8)

â *end example*]

[25)](#footnote-25)[25)](#footnoteref-25)

The same rules apply to initialization of an initializer_list object ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")) with its
 underlying temporary array[.](#footnote-25.sentence-1)
