When is a C ++ destructor called?

The main question is: when does a program call a class destructor method in C ++? I was told that it is called whenever an object goes out of scope or is exposed to delete

More specific questions:

1) If the object is created using a pointer, and this pointer is later deleted or receives a new address, which indicates whether the object that it points to its destructor (provided that nothing else points to it)?

2) In response to question 1, what determines when an object goes beyond (does not apply to when an object leaves a given {block}). So, in other words, when is a destructor called an object in a linked list?

3) Do you ever want to call the destructor manually?

+75
c ++ destructor
Apr 10 2018-12-12T00:
source share
9 answers

1) If the object is created using a pointer, and this pointer is later deleted or receives a new address, which indicates whether the object that it points to its destructor (provided that nothing else points to it)?

It depends on the type of pointers. For example, smart pointers often delete their objects when they are deleted. Regular pointers do not. The same is true when a pointer is made to point to another object. Some smart pointers destroy an old object or destroy it if it no longer has references. Ordinary pointers do not have such skills. They simply contain the address and allow you to perform operations on the objects to which they point, specially doing it.

2) In response to question 1, what determines when an object goes beyond (does not apply to when an object leaves a given {block}). So, in other words, when is a destructor called an object in a linked list?

This is before implementing a linked list. Typical collections destroy all their contained objects when they are destroyed.

Thus, a linked list of pointers usually destroys pointers, but not the objects they point to. (This may be correct; they may be references by other pointers.) A linked list specifically designed to indicate pointers can delete objects on their own.

A linked list of smart pointers can automatically delete objects when pointers are deleted or do so if they no longer have references. It is up to you to choose the parts that do what you want.

3) Do you ever want to call the destructor manually?

Sure. For example, if you want to replace an object with another object of the same type, but do not want to free memory, just to allocate it again. You can destroy the old object in place and build a new one. (However, this is usually a bad idea.)

 // pointer is destroyed because it goes out of scope, // but not the object it pointed to. memory leak if (1) { Foo *myfoo = new Foo("foo"); } // pointer is destroyed because it goes out of scope, // object it points to is deleted. no memory leak if(1) { Foo *myfoo = new Foo("foo"); delete myfoo; } // no memory leak, object goes out of scope if(1) { Foo myfoo("foo"); } 
+47
Apr 10 2018-12-12T00:
source share

Others have already addressed other issues, so I’ll just look at one point: do you ever want to manually delete an object.

The answer is yes. @DavidSchwartz gave one example, but it is rather unusual. I will give an example that, under the hood of what many C ++ programmers use all the time: std::vector (and std::deque , although it is not used quite like that).

As most people know, std::vector allocates a larger block of memory when / if you add more elements than the current distribution can hold. However, when he does this, he has a memory block that can hold more objects than it currently does in the vector.

To deal with this, what vector does under covers, allocates raw memory through an Allocator object (which, unless you specify otherwise, means that it uses ::operator new ). Then, when you use (for example) push_back to add an element to vector , inside the vector uses placement new to create an element in the (previously) unused part of its memory space.

Now, what happens when / if you erase an element from a vector? It cannot just use delete - which will free the entire block of memory; it must destroy one object in this memory without destroying the others, or freeing any of the memory block that it controls (for example, if you erase 5 elements from a vector and then push_back 5 more elements, this is guaranteed that the vector does not redistribute memory when you do it.

To do this, the vector directly destroys the objects in memory, explicitly calling the destructor, and not using delete .

If perhaps someone else should have written a container using continuous storage something like vector (or some version of this, for example, std::deque really), you will almost certainly want to use the same technique.

Just, for example, consider how you can write code for a circular circular buffer.

 #ifndef CBUFFER_H_INC #define CBUFFER_H_INC template <class T> class circular_buffer { T *data; unsigned read_pos; unsigned write_pos; unsigned in_use; const unsigned capacity; public: circular_buffer(unsigned size) : data((T *)operator new(size * sizeof(T))), read_pos(0), write_pos(0), in_use(0), capacity(size) {} void push(T const &t) { // ensure there room in buffer: if (in_use == capacity) pop(); // construct copy of object in-place into buffer new(&data[write_pos++]) T(t); // keep pointer in bounds. write_pos %= capacity; ++in_use; } // return oldest object in queue: T front() { return data[read_pos]; } // remove oldest object from queue: void pop() { // destroy the object: data[read_pos++].~T(); // keep pointer in bounds. read_pos %= capacity; --in_use; } // release the buffer: ~circular_buffer() { operator delete(data); } }; #endif 

Unlike standard containers, this directly uses operator new and operator delete . For real use, you probably want to use a dispenser class, but for now it will be more distracting than contributing (IMO, anyway).

+10
Apr 10 '12 at 2:20
source share
  • When you create an object with new , you are responsible for calling delete . When you create an object with make_shared , the resulting shared_ptr is responsible for storing count and call delete when the usage counter goes to zero.
  • Leaving the scope means rejecting the block. This is when the destructor is called, assuming that the object was not allocated using new (i.e., this is a stack object).
  • About when you need to explicitly call the destructor is the allocation of the object placement new .
+5
Apr 10 2018-12-12T00:
source share

1) Objects are not created "through pointers". There is a pointer that is assigned to any object that you are 'new'. Assuming this is what you mean, if you call “delete” on a pointer, it will actually delete (and call the destructor) the object that causes the difference of pointers. If you assign a pointer to another object, a memory leak will occur; nothing in C ++ will collect your garbage for you.

2) These are two separate issues. A variable goes out of scope when the stack stack in which it was declared flies out of the stack. This is usually when you leave the block. Objects on the heap never go beyond, although their pointers to the stack can. Nothing in particular guarantees that the destructor of the object in the linked list will be called.

3) Not really. There might be Deep Magic, which would suggest otherwise, but usually you want to match your “new” keywords with your “delete” keywords and put everything in your destructor to make sure that it cleans itself properly. If you do not, be sure to comment on the destructor with specific instructions to anyone who uses the class about how they should manually clear the resources of the object.

+3
Apr 10 2018-12-12T00:
source share

To give a detailed answer to question 3: yes, there are rare cases where you can explicitly call the destructor, in particular, as a comparison with a new placement, as dasblinkenlight notes.

To give a concrete example of this:

 #include <iostream> #include <new> struct Foo { Foo(int i_) : i(i_) {} int i; }; int main() { // Allocate a chunk of memory large enough to hold 5 Foo objects. int n = 5; char *chunk = static_cast<char*>(::operator new(sizeof(Foo) * n)); // Use placement new to construct Foo instances at the right places in the chunk. for(int i=0; i<n; ++i) { new (chunk + i*sizeof(Foo)) Foo(i); } // Output the contents of each Foo instance and use an explicit destructor call to destroy it. for(int i=0; i<n; ++i) { Foo *foo = reinterpret_cast<Foo*>(chunk + i*sizeof(Foo)); std::cout << foo->i << '\n'; foo->~Foo(); } // Deallocate the original chunk of memory. ::operator delete(chunk); return 0; } 

The goal of this kind is to separate memory allocation from building an object.

+3
Apr 10 2018-12-12T00:
source share
  • Pointers . Regular pointers do not support RAII. Without explicit delete will be garbage. Fortunately, C ++ has auto-sciences that handle this for you!

  • Area . Think about when a variable becomes invisible to your program. This is usually at the end of {block} , as you indicate.

  • Manual destruction . Never try. Just let scope and RAII do the magic for you.

+2
Apr 10 2018-12-12T00:
source share

Whenever you use the "new", that is, attach the address to the pointer or, if you want, you require space on the heap, you need to "delete" it. 1.yes, when you delete something, the destructor is called.
2. When the linked list destructor is called, its object destructor is called. But if they are pointers, you need to delete them manually. 3. When the space is declared "new."

+1
Apr 10 2018-12-12T00:
source share

Yes, the destructor (aka dtor) is called when an object goes out of scope, if it is on the stack, or when you call delete pointer to the object.

  • If the pointer is deleted via delete , then dtor will be called. If you reassign the pointer without calling delete first, you will get a memory leak because the object still exists in memory. In the latter case, dtor is not called.

  • A good implementation of a linked list will cause dtor of all the objects in the list when the list is destroyed (because you either called some method to destroy it, or you left the scope). It depends on the implementation.

  • I doubt it, but I won’t be surprised if there are any strange circumstances.

0
Apr 10 2018-12-12T00
source share

If the object is not created via the pointer (for example, A a1 = A ();), the destructor is called when the object is destroyed, always when the function in which the object is located is completed. For example: <w>

 void func() { ... A a1 = A(); ... }//finish 


the destructor is called when the code is executed on the "finish" line.

If an object is created using a pointer (for example, A * a2 = new A ();), the destructor is called when the pointer is deleted (deletes a2;). If the point is not deleted explicitly by the user or before deleting the new address, a memory leak will occur. This is mistake.

In a linked list, if we use std :: list <>, we don’t need to worry about the descriptor or memory leak, because std :: list <> has finished all this for us. In the linked list that we ourselves wrote, we must write a descriptor and delete the explictly.Otherwise pointer, this will cause a memory leak.

We rarely call the destructor manually. This is the function that provides the system.

Sorry for my bad english!

0
Apr 10 2018-12-12T00:
source share



All Articles