An explicit call to the destructor does not destroy my object, why?

I call the destructor to free the memory, but it does not delete my object. What is the reason for this?

my code looks like this:

class A { public: int a; A() { cout << "a" << endl; } }; class B :public A { public: int b; B() { cout << "b" << endl; a = 10; b = 20; } ~B() { cout << a << b << endl; } }; 

and I use it like:

 int main() { { B b; b.~B(); bb=100; // why this step is executed? } int x; cin>>x; return 0; } 
+6
source share
7 answers

I call the destructor to free memory

What for? At the language level, the destructor does not free the memory occupied by the object itself.

A nontrivial destructor ends the lifetime of the object, but does not end the duration of the storage of the object. This means that the memory remains allocated, it just becomes "raw" (uninitialized). Thus, in this sense, it destroys your object.

Meanwhile, the trivial destructor has no effect whatsoever. Even if you call it explicitly, the lifetime of the object does not end.

In your case, the destructor B::~B nontrivial, which formally means that by calling it, you have ended the lifetime of your object. You destroyed it as much as a local object can be destroyed. But the memory remains . Trying to access this memory as object B simply leads to undefined behavior.

In fact, there is no way to manually free the memory occupied by a local object. Local memory is always freed automatically.

+19
source

You don't call a destructor like that (well, you can, but it hasn't been done at all).

For automatic variables such as b , the destructor will be called at some point when the variable goes out of scope. You never need to explicitly call the destructor.

For objects allocated on the heap with new , the destructor will be called after you delete . In this case, you also do not call the destructor explicitly.

C ++ 03 at 12.4 Destructors :

Destructors are called implicitly:

  • for a constructed object with a static storage duration (3.7.1) at the end of the program;
  • for a constructed object with automatic storage time (3.7.2), when the block in which the object is created is called;
  • for the created temporary object, when the lifetime of the temporary object ends;
  • for the constructed object selected by the new expression, using the delete expression;
  • in several situations due to exception handling.

Destructors can also be explicitly called.

Note: calls to destructors are clearly needed. One use of such calls is for objects placed at specific addresses using a new expression with the possibility of placement. Such use of explicit placement and destruction of objects may be required to cope with the allocated hardware resources and to write memory controls.

You especially do not do what you are trying to do, since the destructor will be called twice, once explicitly, and you will also once implicitly when b goes beyond. From the same section of the standard:

As soon as the destructor is called for the object, the object no longer exists; undefined behavior if the destructor is called for an object whose lifetime has expired. Example: if the destructor for an automatic object is explicitly called, and then the block is left in a way that usually causes implicit destruction of the object, the behavior is undefined.

This text remains unchanged in the last C ++ 11 project that I have (n3225, November 2010), and it is unlikely that it would essentially change between this and the statement in August 2011.

+5
source

What you do actually causes undefined behavior ... just because you called the destructor does not mean that the memory is reset or necessarily “fixed” and inaccessible (especially in the case of an automatic variable that was allocated on the stack, not a bunch ) It may be, but it remains with the implementation, and usually it is not executed due to performance reasons, which is usually the reason for using C ++. Therefore, you can theoretically access the values ​​at the memory address that the object occupied after calling the destructor ... but again, this behavior is undefined, and you may encounter almost everything related to a segmentation error, a silent error that damages the memory elsewhere etc.

+4
source

It runs because you wrote code that said you want this to happen. The compiler just does what you told him to.

What you are doing is probably not “freeing up memory," as you suggested. Instead, it simply calls the destructor. Destructors do not free the memory occupied by the objects to which they are called. They free the memory allocated by the object (for example, by calling the destructors of member variables or calling free or delete on other things), but the memory of the object itself is freed up elsewhere either by the internal delete or compiler operations when clearing automatic variables (which is a declaration of B b ) . Even closing the visibility block probably does not free up memory for b ; compilers usually determine how much stack space they will need for the entire routine and allocate all this when they enter. The memory occupied by this object b is reserved for b when entering the inner region, and upon exit, the destructor is called automatically.

+3
source

Your object has been destroyed, but its memory space still remains until it goes out of scope.

+1
source

Why not? Your object has been destroyed, but its memory space is still around until it goes out of scope, where it will be destroyed again. This behavior is undefined to do what you do.

0
source

Destructors were not intended to be called directly. Basically this is just another (special) class method. If you want to Uninitialize your object, and then you can still use it, you can make your own method:

 class B: public A { public: int b; B() {cout<<"b"<<endl;a=10;b=20;} ~B() {Release(); cout<<a<<b<<endl;} void Release() { cout<<"Releasing B"; b = 0; } }; int main() { { B b; b.Release(); bb=100; // why this step is executed? } int x; cin>>x; return 0; } 

Otherwise, B will be deleted out of scope:

 int main() { { B b; bb = 100; //OK } bb = 100; //compile time error int x; cin>>x; return 0; } 
0
source

Source: https://habr.com/ru/post/897196/


All Articles