Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Destructors

      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
       
       

      A destructor is a specialmember function that is called when thelifetime of an object ends. The purpose of the destructor is to free the resources that the object may have acquired during its lifetime.

      A destructor cannot be acoroutine.

      (since C++20)

      Contents

      [edit]Syntax

      Destructors(until C++20)Prospective destructors(since C++20) are declared using memberfunction declarators of the following form:

      class-name-with-tilde(parameter-list (optional))except (optional)attr (optional)
      class-name-with-tilde - anidentifier expression, possibly followed by a list ofattributes, and(since C++11) possibly enclosed by a pair parentheses
      parameter-list -parameter list (must be either empty orvoid)
      except -

      dynamic exception specification

      (until C++11)

      eitherdynamic exception specification
      ornoexcept specification

      (since C++11)
      (until C++17)

      noexcept specification

      (since C++17)
      attr -(since C++11) a list ofattributes

      The only specifiers allowed in thedeclaration specifiers of a prospective(since C++20) destructor declaration areconstexpr,(since C++11)friend,inline andvirtual (in particular, no return type is allowed).

      The identifier expression ofclass-name-with-tilde must have one of the following forms:

      • For classes, the identifier expression is~ followed by theinjected-class-name of the immediately-enclosing class.
      • For class templates, the identifier expression is~ followed bya class name that names thecurrent instantiation(until C++20)the injected-class-name(since C++20) of the immediately-enclosing class template.
      • Otherwise, the identifier expression is a qualified identifier whose terminal unqualified identifier is~ followed by the injected-class name of the class nominated by the non-terminal parts of the qualified identifier.

      [edit]Explanation

      The destructor is implicitly invoked whenever an object'slifetime ends, which includes

      • thread exit, for objects with thread-local storage duration
      (since C++11)
      • end of scope, for objects with automatic storage duration and for temporaries whose life was extended by binding to a reference
      • delete expression, for objects with dynamic storage duration
      • end of the fullexpression, for nameless temporaries
      • stack unwinding, for objects with automatic storage duration when an exception escapes their block, uncaught.

      The destructor can also be invoked explicitly.

      Prospective destructor

      A class may have one or more prospective destructors, one of which is selected as the destructor for the class.

      In order to determine which prospective destructor is the destructor, at the end of the definition of the class,overload resolution is performed among prospective destructors declared in the class with an empty argument list. If the overload resolution fails, the program is ill-formed. Destructor selection does notodr-use the selected destructor, and the selected destructor may be deleted.

      All prospective destructors are special member functions. If no user-declared prospective destructor is provided for classT, the compiler will alwaysimplicitly declare one, and the implicitly-declared prospective destructor is also the destructor forT.

      Run this code
      #include <cstdio>#include <type_traits> template<typename T>struct A{    ~A() requiresstd::is_integral_v<T>{std::puts("~A, T is integral");}    ~A() requiresstd::is_pointer_v<T>{std::puts("~A, T is a pointer");}    ~A(){std::puts("~A, T is anything else");}}; int main(){    A<int> a;    A<int*> b;    A<float> c;}

      Output:

      ~A, T is anything else~A, T is a pointer~A, T is integral
      (since C++20)

      [edit]Potentially-invoked destructor

      The destructor for classT ispotentially invoked in the following situations:

      If a potentially-invoked destructor is deleted or(since C++11) not accessible from the context of the invocation, the program is ill-formed.

      [edit]Implicitly-declared destructor

      If no user-declared prospective(since C++20) destructor is provided for aclass type, the compiler will always declare a destructor as aninlinepublic member of its class.

      As with any implicitly-declared special member function, the exception specification of the implicitly-declared destructor is non-throwing unlessthe destructor of any potentially-constructed base or member ispotentially-throwing(since C++17)implicit definition would directly invoke a function with a different exception specification(until C++17). In practice, implicit destructors arenoexcept unless the class is "poisoned" by a base or member whose destructor isnoexcept(false).

      [edit]Implicitly-defined destructor

      If an implicitly-declared destructor is not deleted, it is implicitly defined (that is, a function body is generated and compiled) by the compiler when it isodr-used. This implicitly-defined destructor has an empty body.

      If this satisfies the requirements of aconstexpr destructor(until C++23)constexpr function(since C++23), the generated destructor isconstexpr.

      (since C++20)


      Deleted destructor

      The implicitly-declared or explicitly-defaulted destructor for classT is defined as deleted if any of the following conditions is satisfied:

      • is deleted or inaccessible from the destructor ofT, or
      • in the case of the subobject being avariant member, is non-trivial.
      (until C++26)
      • T is not a union, and has a non-variantpotentially constructed subobject of class typeM (or possibly multidimensional array thereof) such thatM has a destructor that is deleted or inaccessible from the destructor ofT.
      • T is a union, and any of the following conditions is satisfied:
      • The overload resolution to select a constructor to default-initialize an object of typeT either fails or selects a constructor that is either deleted or non-trivial.
      • T has a variant memberV of class typeM (or possibly multidimensional array thereof) whereV has a default initializer andM has a destructor that is non-trivial.
      (since C++26)
      • an ambiguity, or
      • a function that is deleted or inaccessible from the destructor.

      An explicitly-defaulted prospective destructor forT is defined as deleted if it is not the destructor forT.

      (since C++20)
      (since C++11)

      [edit]Trivial destructor

      The destructor for classT is trivial if all following conditions are satisfied:

      • The destructor isimplicitly-declared(until C++11)notuser-provided(since C++11).
      • The destructor is not virtual.
      • All direct base classes have trivial destructors.
      • Every non-static data member of class type (or array of class type) has a trivial destructor.
      (until C++26)
      • EitherT is a union, or every non-variant non-static data member of class type (or array of class type) has a trivial destructor.
      (since C++26)

      A trivial destructor is a destructor that performs no action. Objects with trivial destructors don't require adelete expression and may be disposed of by simply deallocating their storage. All data types compatible with the C language (POD types) are trivially destructible.

      [edit]Destruction sequence

      For both user-defined or implicitly-defined destructors, after executing the body of the destructor and destroying any automatic objects allocated within the body, the compiler calls the destructors for all non-static non-variant data members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes inreverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is ofmost derived class, it calls the destructors of all virtual bases.

      Even when the destructor is called directly (e.g.obj.~Foo();), thereturn statement in~Foo() does not return control to the caller immediately: it calls all those member and base destructors first.

      [edit]Virtual destructors

      Deleting an object through pointer to base invokes undefined behavior unless the destructor in the base class isvirtual:

      class Base{public:virtual ~Base(){}}; class Derived:public Base{}; Base* b= new Derived;delete b;// safe

      A common guideline is that a destructor for a base class must beeither public and virtual or protected and nonvirtual.

      [edit]Pure virtual destructors

      Aprospective(since C++20) destructor may be declaredpure virtual, for example in a base class which needs to be made abstract, but has no other suitable functions that could be declared pure virtual. A pure virtual destructor must have a definition, since all base class destructors are always called when the derived class is destroyed:

      class AbstractBase{public:virtual ~AbstractBase()=0;};AbstractBase::~AbstractBase(){} class Derived:public AbstractBase{}; // AbstractBase obj; // compiler errorDerived obj;// OK

      [edit]Exceptions

      As any other function, a destructor may terminate by throwing anexception(this usually requires it to be explicitly declarednoexcept(false))(since C++11), however if this destructor happens to be called duringstack unwinding,std::terminate is called instead.

      Althoughstd::uncaught_exceptions may sometimes be used to detect stack unwinding in progress, it is generally considered bad practice to allow any destructor to terminate by throwing an exception. This functionality is nevertheless used by some libraries, such asSOCI andGalera 3, which rely on the ability of the destructors of nameless temporaries to throw exceptions at the end of the full expression that constructs the temporary.

      std::experimental::scope_success in Library fundamental TS v3 may havea potentially-throwing destructor, which throws an exception when the scope is exited normally and the exit function throws an exception.

      [edit]Notes

      Calling a destructor directly for an ordinary object, such as a local variable, invokes undefined behavior when the destructor is called again, at the end of scope.

      In generic contexts, the destructor call syntax can be used with an object of non-class type; this is known as pseudo-destructor call: seemember access operator.

      Feature-test macroValueStdFeature
      __cpp_trivial_union202502L(C++26)Relaxing the triviality requirements for special member functions of unions

      [edit]Example

      Run this code
      #include <iostream> struct A{int i;     A(int num): i(num){std::cout<<"ctor a"<< i<<'\n';} (~A)()// but usually ~A(){std::cout<<"dtor a"<< i<<'\n';}}; A a0(0); int main(){    A a1(1);    A* p; {// nested scope        A a2(2);        p= new A(3);}// a2 out of scope     delete p;// calls the destructor of a3}

      Output:

      ctor a0ctor a1ctor a2ctor a3dtor a2dtor a3dtor a1dtor a0

      [edit]Defect reports

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

      DRApplied toBehavior as publishedCorrect behavior
      CWG 193C++98whether automatic objects in a destructor are
      destroyed before or after the destruction of the
      class's base and member subobjects was unspecified
      they are destroyed
      before destroying
      those subobjects
      CWG 344C++98the declarator syntax of destructor was defective (had the
      same problem asCWG issue 194 andCWG issue 263
      changed the syntax to a specialized
      function declarator syntax
      CWG 1241C++98static members might be destroyed
      right after destructor execution
      only destroy non-
      static members
      CWG 1353C++98the conditions where implicitly-declared destructors are
      undefined did not consider multi-dimensional array types
      consider these types
      CWG 1435C++98the meaning of “class name” in the
      declarator syntax of destructor was unclear
      changed the syntax to a specialized
      function declarator syntax
      CWG 2180C++98the destructor of a class that is not a most derived class
      would call the destructors of its virtual direct base classes
      it will not call those destructors
      CWG 2807C++20the declaration specifiers could containconstevalprohibited

      [edit]See also

      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/destructor&oldid=181382"

      [8]ページ先頭

      ©2009-2025 Movatter.jp