简体   繁体   中英

explicit call to destructor is not destroying my object why?

I'm calling the destructor to deallocate memory but it is not deleting my object. What is the reason behind it?

my code is 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 am using it like:

int main()
{
    {
        B b;
        b.~B();
        b.b=100;  // why this step is executed?
    }
    int x;
    cin>>x;
    return 0;
}

im calling destructor to deallocate memory

Why? At language level destructor does not deallocate memory occupied by the object itself.

A non-trivial destructor ends object's lifetime , but it doesn't end the object's storage duration . This means that memory remains allocated, it just becomes "raw" (uninitialized). So, in that sense it is destroying your object.

Meanwhile, a trivial destructor has no effect at all. Even if you call it explicitly, the object's lifetime does not end.

In your case the destructor B::~B is non-trivial though, which formally means that by calling it you ended your object's lifetime. You destroyed it as much a local object can be destroyed. But the memory remains . Attempting to access that memory as a B object simply leads to undefined behavior.

In fact, there's no way to manually deallocate memory occupied by a local object. Local memory is always deallocated automatically.

You do not call a destructor like that (well, you can but it's generally not done).

For automatic variables like your b , the destructor will be called at some point when the variable goes out of scope. You don't ever need to call the destructor explicitly.

For objects allocated on the heap with new , the destructor will be called after you delete them. In this case, you also don't call the destructor explicitly.

C++03 states in 12.4 Destructors :

Destructors are invoked implicitly:

  • for a constructed object with static storage duration (3.7.1) at program termination;
  • for a constructed object with automatic storage duration (3.7.2) when the block in which the object is created exits;
  • for a constructed temporary object when the lifetime of the temporary object ends;
  • for a constructed object allocated by a new-expression, through use of a delete-expression;
  • in several situations due to the handling of exceptions.

Destructors can also be invoked explicitly.

Note: explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specific addresses using a new-expression with the placement option. Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.

You especially don't do what you're trying to do since the destructor will be called twice, once explicitly by you and once implicitly when b goes out of scope. From that same section of the standard:

Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended. Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.

This text remains unchanged in the latest draft of C++11 that I have (n3225, November 2010) and it's unlikely it would have changed in essence between that and approval in August 2011.

What you're doing is actually invoking undefined behavior ... just because you've called the destructor, does not mean that the memory is zeroed out or necessarily "reclaimed" and inaccessable (especially in the case of an automatic variable that was allocated on the stack and not the heap). It could be, but that is left up to the implementation, and typically that is not done due to performance reasons, which is typically the reason for using C++ in the first place. Therefore you can theoretically access the values at the memory address that the object was occupying after calling the destructor ... but again, it's undefined behavior, and you can run into pretty much anything from a segmentation fault, to a silent error that corrupts memory somewhere else, etc.

It's executed because you wrote the code that said you wanted it to happen. The compiler is simply doing what you told it to do.

What you're doing probably doesn't "deallocate memory," as you suggested it would. Instead, it just calls the destructor. Destructors don't deallocate the memory occupied by the objects they're called on. They deallocate memory allocated by the object (such as by calling destructors of member variables, or calling free or delete on other things), but the memory of the object itself is deallocated elsewhere, either by the internal workings of the delete statement, or by the compiler when cleaning up automatic variables (which is what your B b declaration represents). Even the closing of the scope block probably doesn't deallocate any memory for b ; compilers usually figure out how much stack space they'll need for an entire subroutine and allocate it all upon entry. The memory occupied by that B object is reserved for b upon entry to the inner scope, and upon exit, the destructor is called automatically.

您的对象已被破坏但其内存空间仍然存在,直到它超出范围。

Destructors were not designed to call them explicitly. Basically it is just another (special) method of class. If you want to Uninitialize your object and then still be able to use it you could make our 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();
      b.b=100;  // why this step is executed?
    }
    int x;
    cin>>x;
    return 0;
}

Otherwise B will be deleted when out of scope:

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

Why wouldn't? Your object has been destroyed but its memory space is still around until it goes out of scope, where it will be destroyed again by the way. It's undefined behavior to do what you do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM