Why doesn't the C++ default destructor destroy my objects?

前端 未结 13 2060
刺人心
刺人心 2020-12-14 06:59

The C++ specification says the default destructor deletes all non-static members. Nevertheless, I can\'t manage to achieve that.

I have this:

class N         


        
相关标签:
13条回答
  • 2020-12-14 07:22

    Your argument might seem sound but that's not how things work for pointers.

    n is actually being destructed but, what this means is that the N* destructor is being called which, it does NOT destruct whatever object n is pointing to. Think of the N*'s destructor as if it were an int's destructor. It deletes its value, the same happens for a pointer, it deletes the address it is pointing to, but it doesn't need to delete whatever object is located at the address you just deleted.

    0 讨论(0)
  • 2020-12-14 07:25

    It is incorrect to say that the destructor deletes members. It invokes the destructor of each member (and base class), which for built-in types (like pointers) means doing nothing.

    Matching news with deletes is your responsibility (either manually, or with the help of smart pointers).

    0 讨论(0)
  • 2020-12-14 07:26

    Is there any reason why you use a pointer when the pointed-to object seems to belong the contained object? Just store the object by value:

    class M
    {
        N n;
    
    public:
    
        M() : n()
        {
        }
    };
    
    0 讨论(0)
  • 2020-12-14 07:29

    What makes you think the object n points to should be deleted by default? The default destructor destroys the pointer, not what it's pointing to.

    Edit: I'll see if I can make this a little more clear.

    If you had a local pointer, and it went out of scope, would you expect the object it points to to be destroyed?

    {
        Thing* t = new Thing;
    
        // do some stuff here
    
        // no "delete t;"
    }
    

    The t pointer is cleaned up, but the Thing it points to is not. This is a leak. Essentially the same thing is happening in your class.

    0 讨论(0)
  • I think you may be confused about levels of indirection here. When an instance is destroyed, each data member does indeed get destroyed along with it. In your case, when an M is destroyed and M::~M() is called, its variable n really is destroyed. The problem is that n is a N *, so while the pointer is destroyed, the thing it points to is not.

    delete does not work like this. Consider your simple statement:

    delete n;
    

    The above statement destroys the thing that n points to, which is an object of type N. It does not destroy n itself, which is an N * pointer.

    There is a very good reason that M::~M() does not automatically call delete n; which is this: the N object referred to might be shared between several M objects, and if one M were destroyed, the rest would lose the N they were pointing at, leaving horrible dangling pointers everywhere. C++ does not attempt to interpret what you meant to do with your pointers, it just does what you told it to do.

    In short, M really is destroying all of its members when it is destroyed, it's just that this destruction doesn't do what you think it should do. If you want a pointer type which takes ownership of an object and destroys it when the pointer is destroyed, look at std::auto_ptr.

    0 讨论(0)
  • 2020-12-14 07:31

    The default destructor looks like this:

    ~M()
    {
    }
    

    The default destructor does not insert code to do anything with pointed-to things. What if you had n pointing to a stack variable? Automatically inserting a delete n would crash.

    The default destructor calls the destructor on each member of the class (member.~T()). For a pointer, that's a no-op (does nothing), just like myint.~int() does nothing, but for member classes with defined destructors, the destructor is called.

    Here's another example:

    struct MyClass {
    public:
        MyClass() { .. } // doesn't matter what this does
    
        int x;
        int* p;
        std::string s;
        std::vector<int> v;
    };
    

    The default destructor in reality is doing this:

    MyClass::~MyClass()
    {
        // Call destructor on member variables in reverse order
        v.~std::vector<int>(); // frees memory
        s.~std::string();      // frees memory
        p.~int*();             // does nothing, no custom destructor
        x.~int();              // does nothing, no custom destructor
    }
    

    Of course, if you define a destructor, the code in your destructor runs before the member variables are destroyed (obviously, otherwise they would not be valid!).

    0 讨论(0)
提交回复
热议问题