Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Lifetime

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
       

      Everyobject andreference has alifetime, which is a runtime property: for any object or reference, there is a point of execution of a program when its lifetime begins, and there is a moment when it ends.

      The lifetime of an object begins when:

      • if the object is aunion member or subobject thereof, its lifetime only begins if that union member is the initialized member in the union, or it is made active,
      • if the object is nested in a union object, its lifetime may begin if the containing union object is assigned or constructed by a trivial special member function,
      • an array object's lifetime may also begin if it is allocated bystd::allocator::allocate.

      Some operationsimplicitly create objects ofimplicit-lifetime types in given region of storage and start their lifetime. If a subobject of an implicitly created object is not of an implicit-lifetime type, its lifetime does not begin implicitly.

      The lifetime of an object ends when:

      • if it is of a non-class type, the object is destroyed (maybe via a pseudo-destructor call), or
      • if it is of a class type, thedestructor call starts, or
      • the storage which the object occupies is released, or isreused by an object that is not nested within it.

      Lifetime of an object is equal to or is nested within the lifetime of its storage, seestorage duration.

      The lifetime of areference begins when its initialization is complete and ends as if it were a scalar object.

      Note: the lifetime of the referred object may end before the end of the lifetime of the reference, which makesdangling references possible.

      Lifetimes of non-static data members and base subobjects begin and end followingclass initialization order.

      Contents

      [edit]Temporary object lifetime

      Temporary objects are createdwhen a prvalue ismaterialized so that it can be used as a glvalue, which occurs(since C++17) in the following situations:

      (since C++11)
      • returning a prvalue from a function
      • conversion that creates a prvalue (includingT(a, b, c) andT{})
      (since C++11)
      (until C++17)

      The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary object: seecopy elision.

      (since C++17)


      When an object of typeT is passed to or returned from apotentially-evaluated function call, ifT is one of the following types, implementations are permitted to create temporary objects to hold the function parameter or result object:

      (since C++26)
      • a class type satisfying all following conditions:
        • T has at least one eligiblecopy ormove constructor.
        • Each eligible copy/move constructor ofT is trivial.
        • Thedestructor ofT is either trivial or deleted.

      The temporary object is constructed from the function argument or return value, respectively, and the function’s parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object).

      (until C++26)

      The temporary objects are created as follows:

      • The first such temporary object is constructed from the function argument or return value, respectively.
      • Each successive temporary object is initialized from the previous one as if bydirect-initialization ifT is a scalar type, otherwise by using an eligible trivial constructor.
      • The function parameter or return object is initialized from the final temporary as if by direct initialization ifT is a scalar type, otherwise by using an eligible trivial constructor.

      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.

      (since C++26)

      This latitude is granted to allow objects to be passed to or returned from functions in registers.

      (since C++17)

      All temporary objects are destroyed as the last step in evaluating thefull-expression that (lexically) contains the point where they were created, and if multiple temporary objects were created, they are destroyed in the order opposite to the order of creation. This is true even if that evaluation ends in throwing an exception.

      There are the following exceptions from that:

      • The lifetime of a temporary object may be extended by binding to a reference, seereference initialization for details.
      • The lifetime of a temporary object created when evaluating the default arguments of a default or copy constructor used to initialize or copy an element of an array ends before the next element of the array begins initialization.
      • The lifetime of a temporary object created in astructured binding declaration (introduced by the initializer for a variable with unique name) is extended to the end of the structured binding declaration.
      (since C++17)
      • The lifetime of a temporary object created in therange-initializer of arange-for statement that would otherwise be destroyed at the end of therange-initializer is extended to the end of the loop body.
      (since C++23)

      [edit]Storage reuse

      A program is not required to call the destructor of an object to end its lifetime if the object istrivially-destructible (be careful that the correct behavior of the program may depend on the destructor). However, if a program ends the lifetime of a non-trivially destructible object that is a variable explicitly, it must ensure that a new object of the same type is constructed in-place (e.g. via placementnew) before the destructor may be called implicitly, i.e. due to scope exit or exception for automatic objects, due to thread exit for thread-local objects,(since C++11) or due to program exit for static objects; otherwise the behavior is undefined.

      class T{};// trivial struct B{    ~B(){}// non-trivial}; void x(){longlong n;// automatic, trivial    new(&n)double(3.14);// reuse with a different type okay}// okay void h(){    B b;// automatic non-trivially destructible    b.~B();// end lifetime (not required, since no side-effects)    new(&b) T;// wrong type: okay until the destructor is called}// destructor is called: undefined behavior

      It is undefined behavior to reuse storage that is or was occupied by a const complete object of static, thread-local,(since C++11) or automatic storage duration because such objects may be stored in read-only memory:

      struct B{    B();// non-trivial    ~B();// non-trivial};const B b;// const static void h(){    b.~B();// end the lifetime of b    new(const_cast<B*>(&b))const B;// undefined behavior: attempted reuse of a const}

      When evaluating anew expression, storage is considered reused after it is returned from theallocation function, but before the evaluation of theinitializer of the new expression:

      struct S{int m;}; void f(){    S x{1};    new(&x) S(x.m);// undefined behavior: the storage is reused}

      If a new object is created at the address that was occupied by another object, then all pointers, references, and the name of the original object will automatically refer to the new object and, once the lifetime of the new object begins, can be used to manipulate the new object, but only if the original object is transparently replaceable by the new object.

      If all following conditions are satisfied, objectx istransparently replaceable by objecty:

      • The storage fory exactly overlays the storage location whichx occupied.
      • y is of the same type asx (ignoring the top-level cv-qualifiers).
      • x is not a complete const object.
      • Neitherx nory is a base class subobject, or a member subobject declared with[[no_unique_address]](since C++20).
      • One of the following conditions is satisfied:
      • x andy are both complete objects.
      • x andy are direct subobjects of objectsox andoy respectively, andox is transparently replaceable byoy.
      struct C{int i;void f();const C& operator=(const C&);}; const C& C::operator=(const C& other){if(this!=&other){        this->~C();// lifetime of *this ends        new(this) C(other);// new object of type C created        f();// well-defined}return*this;} C c1;C c2;c1= c2;// well-definedc1.f();// well-defined; c1 refers to a new object of type C

      If the conditions listed above are not met, a valid pointer to the new object may still be obtained by applying the pointer optimization barrierstd::launder:

      struct A{virtualint transmogrify();}; struct B: A{int transmogrify() override{::new(this) A;return2;}}; inlineint A::transmogrify(){::new(this) B;return1;} void test(){    A i;int n= i.transmogrify();// int m = i.transmogrify(); // undefined behavior:// the new A object is a base subobject, while the old one is a complete objectint m=std::launder(&i)->transmogrify();// OKassert(m+ n==3);}
      (since C++17)

      Similarly, if an object is created in the storage of a class member or array element, the created object is only a subobject (member or element) of the original object's containing object if:

      • the lifetime of the containing object has begun and not ended
      • the storage for the new object exactly overlays the storage of the original object
      • the new object is of the same type as the original object (ignoring cv-qualification).

      Otherwise, the name of the original subobject cannot be used to access the new object withoutstd::launder:

      This section is incomplete
      Reason: an appropriate example
      (since C++17)

      [edit]Providing storage

      As a special case, objects can be created in arrays ofunsignedchar orstd::byte(since C++17) (in which case it is said that the arrayprovides storage for the object) if

      • the lifetime of the array has begun and not ended
      • the storage for the new object fits entirely within the array
      • there is no array object that satisfies these constraints nested within the array.

      If that portion of the array previously provided storage for another object, the lifetime of that object ends because its storage was reused, however the lifetime of the array itself does not end (its storage is not considered to have been reused).

      template<typename...T>struct AlignedUnion{    alignas(T...)unsignedchar data[max(sizeof(T)...)];}; int f(){    AlignedUnion<int,char> au;int*p= new(au.data)int;// OK, au.data provides storagechar*c= new(au.data)char();// OK, ends lifetime of *pchar*d= new(au.data+1)char();return*c+*d;// OK}

      [edit]Access outside of lifetime

      Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, the behaviors of the following uses of the glvalue expression that identifies that object are undefined, unless the object is being constructed or destructed (separate set of rules applies):

      1. Access the object.
      2. Access to a non-static data member or a call to a non-static member function.
      3. Binding a reference to a virtual base class subobject.
      4. dynamic_cast ortypeid expressions.

      The above rules apply to pointers as well (binding a reference to virtual base is replaced by implicit conversion to a pointer to virtual base), with two additional rules:

      1. static_cast of a pointer to storage without an object is only allowed when casting to (possibly cv-qualified)void*.
      2. Pointers to storage without an object that were cast to possibly cv-qualifiedvoid* can only bestatic_cast to pointers to possibly cv-qualifiedchar, or possibly cv-qualifiedunsignedchar, or possibly cv-qualifiedstd::byte(since C++17).

      During construction and destruction it is generally allowed to call non-static member functions, access non-static data members, and usetypeid anddynamic_cast. However, because the lifetime either has not begun yet (during construction) or has already ended (during destruction), only specific operations are allowed. For one restriction, seevirtual function calls during construction and destruction.

      [edit]Notes

      Until the resolution ofCWG issue 2256, the end of lifetime rules are different between non-class objects (end of storage duration) and class objects (reverse order of construction):

      struct A{int* p;    ~A(){std::cout<<*p;}// undefined behavior since CWG2256: n does not outlive a// well-defined until CWG2256: prints 123}; void f(){    A a;int n=123;// if n did not outlive a, this could have been optimized out (dead store)    a.p=&n;}

      Until the resolution ofRU007, a non-static member of a const-qualified type or a reference type prevents its containing object from being transparently replaceable, which makesstd::vector andstd::deque hard to implement:

      struct X{constint n;};union U{ X x;float f;}; void tong(){    U u={{1}};    u.f=5.f;// OK: creates new subobject of 'u'    X*p= new(&u.x) X{2};// OK: creates new subobject of 'u'assert(p->n==2);// OKassert(u.x.n==2);// undefined until RU007:// 'u.x' does not name the new subobjectassert(*std::launder(&u.x.n)==2);// OK even until RU007}

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 119C++98an object of a class type with a non-trivial constructor can
      only start its lifetime when the constructor call has completed
      lifetime also started
      for other initializations
      CWG 201C++98lifetime of a temporary object in a default argument
      of a default constructor was required to end
      when the initialization of the array completes
      lifetime ends before
      initializing the next
      element (also resolves
      CWG issue 124)
      CWG 274C++98an lvalue designating an out-of-lifetime object could be
      used as the operand of static_cast only if the conversion
      was ultimately to cv-unqualifiedchar& orunsignedchar&
      cv-qualifiedchar&
      andunsignedchar&
      also allowed
      CWG 597C++98the following behaviors were undefined:
      1. a pointer to an out-of-lifetime object is implicitly
      converted to a pointer to a non-virtual base class
      2. an lvalue referring to an out-of-lifetime object
      is bound to a reference to a non-virtual base class
      3. an lvalue referring to an out-of-lifetime object is used
      as the operand of astatic_cast (with a few exceptions)
      made well-defined
      CWG 2012C++98lifetime of references was specified to match storage duration,
      requiring that extern references are alive before their initializers run
      lifetime begins
      at initialization
      CWG 2107C++98the resolution ofCWG issue 124 was not applied to copy constructorsapplied
      CWG 2256C++98lifetime of trivially destructible objects were inconsistent with other objectsmade consistent
      CWG 2470C++98more than one arrays could provide storage for the same objectonly one provides
      CWG 2489C++98char[] cannot provide storage, but objects
      could be implicitly created within its storage
      objects cannot be
      implicitly created within
      the storage ofchar[]
      CWG 2527C++98if a destructor is not invoked because of reusing storage and the
      program depends on its side effects, the behavior was undefined
      the behavior is well-
      defined in this case
      CWG 2721C++98the exact time point of storage reuse was unclear for placementnewmade clear
      CWG 2849C++23function parameter objects were considered as temporary
      objects for range-for loop temporary object lifetime extension
      not considered as
      temporary objects
      CWG 2854C++98exception objects were temporary objectsthey are not
      temporary objects
      CWG 2867C++17the lifetime of temporary objects created in
      structured binding declarations were not extended
      extended to the end
      of the declaration
      P0137R1C++98creating an object in an array ofunsignedchar reused its storageits storage is not reused
      P0593R6C++98a pseudo-destructor call had no effectsit destroys the object
      P1971R0C++98a non-static data member of a const-qualified type or a reference type
      prevented its containing object from being transparently replaceable
      restriction removed
      P2103R0C++98transparently replaceability did not require keeping the original structurerequires

      [edit]References

      • C++23 standard (ISO/IEC 14882:2024):
      • 6.7.3 Object lifetime [basic.life]
      • 11.9.5 Construction and destruction [class.cdtor]
      • C++20 standard (ISO/IEC 14882:2020):
      • 6.7.3 Object lifetime [basic.life]
      • 11.10.4 Construction and destruction [class.cdtor]
      • C++17 standard (ISO/IEC 14882:2017):
      • 6.8 Object lifetime [basic.life]
      • 15.7 Construction and destruction [class.cdtor]
      • C++14 standard (ISO/IEC 14882:2014):
      • 3 Object lifetime [basic.life]
      • 12.7 Construction and destruction [class.cdtor]
      • C++11 standard (ISO/IEC 14882:2011):
      • 3.8 Object lifetime [basic.life]
      • 12.7 Construction and destruction [class.cdtor]
      • C++03 standard (ISO/IEC 14882:2003):
      • 3.8 Object lifetime [basic.life]
      • 12.7 Construction and destruction [class.cdtor]
      • C++98 standard (ISO/IEC 14882:1998):
      • 3.8 Object lifetime [basic.life]
      • 12.7 Construction and destruction [class.cdtor]

      [edit]See also

      C documentation forLifetime
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/lifetime&oldid=183379"

      [8]ページ先頭

      ©2009-2025 Movatter.jp