[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 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 using id = T; int i = 1;int&& a = id{1, 2, 3}[i]; // temporary array has same lifetime as aconst int& b = static_cast(0); // temporary int has same lifetime as bint&& c = cond ? id{1, 2, 3}[i] : static_cast(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& 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)