|
1 | 1 | ---
|
2 | 2 | description: "Learn more about: Destructors (C++)"
|
3 | 3 | title: "Destructors (C++)"
|
4 |
| -ms.date: "07/20/2019" |
| 4 | +ms.date: "11/29/2023" |
5 | 5 | helpviewer_keywords: ["objects [C++], destroying", "destructors, C++"]
|
6 | 6 | ---
|
7 | 7 | # Destructors (C++)
|
8 | 8 |
|
9 |
| -A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to **`delete`** or **`delete[]`**. A destructor has the same name as the class, preceded by a tilde (`~`). For example, the destructor for class `String` is declared: `~String()`. |
| 9 | +A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to **`delete`** or **`delete[]`**. A destructor has the same name as the class and is preceded by a tilde (`~`). For example, the destructor for class `String` is declared: `~String()`. |
10 | 10 |
|
11 |
| -If you don't define a destructor, the compiler provides a default one; for many classes this is sufficient. You only need to define a custom destructor when the class stores handles to system resources that need to be released, or pointers that own the memory they point to. |
| 11 | +If you don't define a destructor, the compiler provides a default one, and for some classes this is sufficient. You need to define a custom destructor when the class maintains resources that must be explicitly released, such as handles to system resources or pointers to memory that should be released when an instance of the class is destroyed. |
12 | 12 |
|
13 | 13 | Consider the following declaration of a `String` class:
|
14 | 14 |
|
@@ -58,27 +58,19 @@ Destructors are functions with the same name as the class but preceded by a tild
|
58 | 58 | Several rules govern the declaration of destructors. Destructors:
|
59 | 59 |
|
60 | 60 | - Don't accept arguments.
|
61 |
| -
|
62 | 61 | - Don't return a value (or **`void`**).
|
63 |
| -
|
64 | 62 | - Can't be declared as **`const`**, **`volatile`**, or **`static`**. However, they can be invoked for the destruction of objects declared as **`const`**, **`volatile`**, or **`static`**.
|
65 |
| -
|
66 | 63 | - Can be declared as **`virtual`**. Using virtual destructors, you can destroy objects without knowing their type—the correct destructor for the object is invoked using the virtual function mechanism. Destructors can also be declared as pure virtual functions for abstract classes.
|
67 | 64 |
|
68 | 65 | ## Using destructors
|
69 | 66 |
|
70 | 67 | Destructors are called when one of the following events occurs:
|
71 | 68 |
|
72 | 69 | - A local (automatic) object with block scope goes out of scope.
|
73 |
| -
|
74 |
| -- An object allocated using the **`new`** operator is explicitly deallocated using **`delete`**. If **`delete[]`** is used instead, it would result in undefined behaviour. |
75 |
| -
|
76 |
| -- Objects allocated using the **`new[]`** operator is explicitly deallocated using **`delete[]`**. If **`delete`** is used instead, it would result in undefined behaviour. |
77 |
| -
|
| 70 | +- Use **`delete`** to deallocate an object allocated using **`new`**. Using **`delete[]`** results in undefined behaviour. |
| 71 | +- Use **`delete[]`** to deallocate an object allocated using **`new[]`**. Using **`delete`** results in undefined behaviour. |
78 | 72 | - The lifetime of a temporary object ends.
|
79 |
| -
|
80 | 73 | - A program ends and global or static objects exist.
|
81 |
| -
|
82 | 74 | - The destructor is explicitly called using the destructor function's fully qualified name.
|
83 | 75 |
|
84 | 76 | Destructors can freely call class member functions and access class member data.
|
@@ -160,35 +152,22 @@ class E : public C, public D, virtual public B {};
|
160 | 152 | To determine the order of destruction of the virtual base classes of an object of type `E`, the compiler builds a list by applying the following algorithm:
|
161 | 153 |
|
162 | 154 | 1. Traverse the graph left, starting at the deepest point in the graph (in this case, `E`).
|
163 |
| -
|
164 | 155 | 1. Perform leftward traversals until all nodes have been visited. Note the name of the current node.
|
165 |
| -
|
166 | 156 | 1. Revisit the previous node (down and to the right) to find out whether the node being remembered is a virtual base class.
|
167 |
| -
|
168 | 157 | 1. If the remembered node is a virtual base class, scan the list to see whether it has already been entered. If it isn't a virtual base class, ignore it.
|
169 |
| -
|
170 | 158 | 1. If the remembered node isn't yet in the list, add it to the bottom of the list.
|
171 |
| -
|
172 | 159 | 1. Traverse the graph up and along the next path to the right.
|
173 |
| -
|
174 | 160 | 1. Go to step 2.
|
175 |
| -
|
176 | 161 | 1. When the last upward path is exhausted, note the name of the current node.
|
177 |
| -
|
178 | 162 | 1. Go to step 3.
|
179 |
| -
|
180 | 163 | 1. Continue this process until the bottom node is again the current node.
|
181 | 164 |
|
182 | 165 | Therefore, for class `E`, the order of destruction is:
|
183 | 166 |
|
184 | 167 | 1. The non-virtual base class `E`.
|
185 |
| -
|
186 | 168 | 1. The non-virtual base class `D`.
|
187 |
| -
|
188 | 169 | 1. The non-virtual base class `C`.
|
189 |
| -
|
190 | 170 | 1. The virtual base class `B`.
|
191 |
| -
|
192 | 171 | 1. The virtual base class `A`.
|
193 | 172 |
|
194 | 173 | This process produces an ordered list of unique entries. No class name appears twice. Once the list is constructed, it's walked in reverse order, and the destructor for each of the classes in the list from the last to the first is called.
|
|
0 commit comments