简体   繁体   中英

Why don't compilers call destructor automatically when an object is declared using new operator?

#include<iostream>

using namespace std;

class b {
    public:
        int *a;

    b (int val) {
        *a = val;
    }

    ~b() {
        cout << "destructor" << endl;
        delete a;
    }
};

int main() {
    b *obj = new b(1);
    cout << "end" << endl;
    return 0;
}

Expected output:

destructor
end

Received output:

end

In above code compiler don't call destructor when i make object using new operator but in case of normal object destructor is called successfully. what is the reason behind it?

There are at least three different reasons for creating an object with new ; depending on why you do it, it may or may not be appropriate to delete it when done.

The primary one is that you want to manage its lifetime:

int *create(int i) {
    int *result = new int(i);
    return result;
}

Here, you don't want to destroy the int object when the function ends. Creating it with new means you have to take care of cleaning it up when you're done:

int main() {
    int *xp = create(3);
    std::cout << *xp << 'n';
    delete xp; // I'm done with it
    // more code can go here, but don't use xp
    return 0;
}

Another reason is that the object is an array, and you don't know its size at compile time, so you can't create it as an auto object:

void f(int size) {
    int my_array[size]; // illegal, although some compilers allow it, sigh
    int *my_ptr = new int[size]; // okay, creates array with size elements
    // code that uses my_ptr goes here
    delete[] my_ptr;
}

But that one really should be written with std::vector<int> , which relieves you of the burden of having to remember to delete the array when you're done:

void f(int size) {
    std::vector<int> my_array(size);
    // code that uses my_array
    // no delete, because no explicit new; my_array destructor handles the memory
}

And, finally, you might be dealing with an object that's so large you don't want to clutter the stack with it:

struct my_large_type {
    long double filler[32768];
};

Yes, you can create an object like this on the stack:

void g() {
    my_large_type x;
}

but having many of these things runs the risk of taking up more space than the stack can handle. So you can create them on the free store, with new :

void g() {
    my_large_type *xp = new my_large_type;
    // code that uses *xp goes here
    delete xp;
}

The danger here is that you might forget to delete the memory, or, perhaps worse, that the code between the new and the delete might throw an exception, so the delete doesn't happen -- the memory allocated by new has just leaked.

The right solution here is to use a smart pointer, so that you don't have to handle deleting the object yourself:

void g() {
    std::unique_ptr<my_large_type> xp = new my_large_type;
    // code that uses *xp goes here
    // no delete; destructor will do it for you
}

To summarize: the situations where you want to clean up the new ed object at the end of the block where it was created are best handled by not explicitly using new , but putting the responsibility into a class whose destructor will handle the cleanup. In these examples that would be std::vector and std::unique_ptr . That leaves the case where you want to explicitly manage the lifetime of the object, because you don't know at the time you create it how long it should hang around. In that case, if you don't clean it up, it simply won't get cleaned up; you told the compiler you'd take care of it, and the compiler trusts you.

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