A comprehensive analysis of destructors in C + + _c language

Source: Internet
Author: User
Tags volatile

A destructor is the inverse function of a constructor. They are called when the object is destroyed (disposed). The function is specified as a destructor of the class by placing a tilde (~) in front of the class name. For example, declare a destructor of the String class: ~string ().
In/clr compilation, destructors play a special role in releasing managed and unmanaged resources.
Destructors are typically used to "clean up" this object when an object is no longer needed. Consider the following declaration of the String class:

Spec1_destructors.cpp
#include <string.h>

class String {public
:
  string (char *ch); Declare Constructor
  ~string ();      and destructor.
Private:
  char  *_text;
  size_t sizeoftext;
};

Define the constructor.
String::string (char *ch) {
  sizeoftext = strlen (ch) + 1;

  Dynamically allocate the correct amount of memory.
  _text = new char[Sizeoftext];

  If the allocation succeeds, copy the initialization string.
  if (_text)
   strcpy_s (_text, Sizeoftext, ch);
}

Define the destructor.
String::~string () {
  //deallocate the memory that is previously reserved
  //For this String.
  if (_text)
   delete[] _text;
}

int main () {
  String str ("The Piper in the Glen ...");
}

In the previous example, the destructor string::~string uses the delete operator to dynamically release the space allocated for the text store.
declaring a destructor
A destructor is a function with the same name as the class but preceded by a tilde (~)
The first form of the syntax is used for destructors declared or defined in the class declaration, and the second form is used to define the destructor that is defined outside the class declaration.
Multiple rules manage the declaration of the destructor. destructor:

    • Parameters are not accepted.
    • Cannot specify any return type (including void).
    • The return statement cannot be used for returning a value.
    • cannot be declared as const, volatile, or static. However, you can call them for destructors that are declared as const, volatile, or static.
    • Can be declared as virtual. By using a virtual destructor, you can destroy an object without knowing the type of the object-invoke the correct destructor of the object using the virtual function mechanism. Note that destructors can also be declared as pure virtual functions of abstract classes.

Using constructors

The destructor is called when one of the following events occurs:
Use the delete operator to explicitly deallocate an object that is assigned with the new operator. When you deallocate an object with the delete operator, it frees up memory for most derived objects or for objects that are part of the full object, but not child objects that represent the base class. This "most derived objects" deallocate must be valid only for virtual destructors. In multiple inheritance cases where the type information does not match the underlying type of the actual object, the unassign may fail.
A local (Automatic) object with a block range is out of range.
The lifetime of the temporary object ends.
The program ends, and there are global or static objects.
The destructor was explicitly called using the fully qualified name of the destructor. (For more information, see explicit destructor calls.) )
The situation described in the previous list ensures that all objects can be destroyed by a user-defined method.
If the base class or data member has an accessible destructor and the derived class does not declare a destructor, the compiler generates a destructor. The destructor generated by this compiler will call the base class destructor and destructor for members of the derived type. The default destructor is public.

Destructors are free to invoke class member functions and Access class member data. When you call a virtual function from a destructor, the function that is called is the function of the class that is currently being destroyed.
Order of the destructor
when an object goes out of scope or is deleted, the sequence of events in its complete destructor is as follows:
The destructor of the class is invoked, and the body of the destructor is executed.
These functions are called in the reverse order in which the destructor of Non-static member objects is displayed in the class declaration. The optional member optimization list for the constructs of these members does not affect the order of the construction or the destructor.
Destructors for non-virtual base classes are invoked in the opposite order of declarations.
The destructor of the virtual base class is invoked in the opposite order of the Declaration.

Order_of_destruction.cpp
#include <stdio.h>

struct A1   {virtual ~a1 () {printf ("A1 dtor\n");};
struct A2:A1 {virtual ~a2 () {printf ("A2 dtor\n");};
struct A3:A2 {virtual ~a3 () {printf ("A3 dtor\n");};

struct B1   {~b1 () {printf ("B1 dtor\n");};
struct B2:B1 {~b2 () {printf ("B2 dtor\n");};
struct B3:B2 {~b3 () {printf ("B3 dtor\n");};

int main () {
  A1 * a = new A3;
  Delete A;
  printf ("\ n");

  B1 * b = new B3;
  Delete B;
  printf ("\ n");

  B3 * b2 = new B3;
  Delete B2;
}

Output:

A3 dtor
A2 dtor
A1 dtor B1 dtor B3 dtor
B2
dtor B1 dtor

Virtual base class
The destructor of these virtual base classes (depth first, left to right, and subsequent traversal) is called in the reverse order of the virtual base classes displayed in the directed, non-circular graphics. The following figure describes the inheritance diagram.

To demonstrate the inheritance diagram of a virtual base class
The class headers for the classes shown in the diagram are listed below.

    • Class A
    • Class B
    • Class C:virtual public A, virtual public B
    • Class D:virtual public A, virtual public B
    • Class E:public C, public D, virtual public B

To determine the destructor order of a virtual base class for an object of type E, the compiler will generate a list by applying the following algorithm:

    1. Traverse the diagram to the left and start at the deepest point in the diagram (in this example, E).
    2. Performs a left-shift traversal until all nodes are accessed. Note the name of the current node.
    3. Re-access the previous node (down and to the right) to find out if the node you want to remember is a virtual base class.
    4. If the node you remember is a virtual base class, browse the list to see if it has been entered. If it is not a virtual base class, it is ignored.
    5. If the node you remember is not already included in the list, add it to the bottom of the list.
    6. Traverses the diagram up and traverses the right along the next path.
    7. Go to step 2.
    8. When you are finished using the last up path, note the name of the current node.
    9. Go to step 3.
    10. Continue this process until the bottom node becomes the current node again.

Therefore, for class E, the destructor order is:

    1. Non-Virtual base class E.
    2. Non-Virtual base class D.
    3. Non-Virtual base class C.
    4. Virtual base class B.
    5. Virtual base class A.

This procedure produces an ordered list of unique items. No class name will appear two times. After the list is constructed, the list is traversed in reverse order, and the destructor of each class in the list (from the last to the first) is invoked.

If a constructor or destructor in a class relies on another component that you want to create or retain for longer periods of time (for example, if A's destructor (shown in the figure above) relies on B when it executes its code, the order of the construct or destructor is particularly important, and vice versa.
This interdependence between classes in an inheritance diagram is inherently dangerous because derived classes can later change the leftmost path, changing the order of construction and destructor.
non-Virtual base class
calls a destructor of a non-virtual base class in the reverse order (declaring the base class name in this order). Consider the following class declarations:

Class Multinherit:public Base1, public Base2
...

In the previous example, the destructor of the Base1 is called before the Base2 destructor.
an explicit destructor call
It is rarely necessary to explicitly call a destructor. However, it can be useful to clean up objects that are placed at an absolute address. These objects are typically assigned using a user-defined new operator that takes positional arguments. The delete operator cannot free this memory because it is not allocated from a free store (see the new and delete operators for more information). However, a call to a destructor can perform the appropriate cleanup. To explicitly call the destructor of the object String of the S class, use one of the following statements:

S.string::~string ();   Nonvirtual call
ps->string::~string ();  Nonvirtual call

s.~string ();    Virtual call
ps->~string ();   Virtual Call

You can use representations of explicit calls to the destructor shown earlier, regardless of whether the type defines a destructor. This allows you to make such explicit calls without knowing whether destructors are defined for this type. Explicit invocation of destructors, where undefined destructors are not valid.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.