Using delete on pointers passed as function arguments
Asked Answered
V

9

10

Is it okay( and legal) to delete a pointer that has been passed as a function argument such as this:

#include<iostream>

class test_class{
public:
    test_class():h(9){}
    int h;
    ~test_class(){std::cout<<"deleted";}
};

void delete_test(test_class* pointer_2){
    delete pointer_2;
}

int main(){
    test_class* pointer_1;

    while(true){
        pointer_1 = new test_class;

        //std::cout<<pointer_1->h;

        delete_test(pointer_1);
    }
}

This compiles fine now, but I just want to make sure it'll always be that way.

Vivanvivarium answered 10/12, 2009 at 15:19 Comment(0)
K
14

It will always compile without error.

Whether it's a good thing to pass a pointer into a function and delete it in that function is potentially another story, depending on the specifics of your program.

The main idea you need to consider is that of "ownership" of the pointed-to data. When you pass that pointer, does the calling function have ownership of the data being passed in? i.e. is it in the only place that this data can be referenced from? Are you giving up ownership of the pointed-to-data, with no chance that the calling function is ever going to reference the data again? If so, then you must delete it.

If the calling function might reference the data again, then you must not delete it.

If there are other references to the data through various data structures, then it's not safe to delete this data unless you have some discipline in place in your code to ensure that you will never reference the data again from those places. This is hard to do, and is the source of many programming bugs.

C++ tr1's shared_ptr<> is a smart pointer that helps in these kinds of situations - it manages this ownership concept by keeping a reference count that tracks the number of references to the data. If the reference count is 1, then there is 1 clear owner. If the reference count is larger than 1, then ownership is shared. If the reference count is 0, then there are no more references to the data, and shared_ptr<> will delete it when the shared_ptr<> destructor is called.

Knowitall answered 10/12, 2009 at 15:33 Comment(1)
What I have always found surprising is that deleting the pointer is legal even if it is const.Lethalethal
A
8

Yes, this is valid.

This is commonly done in C (with malloc and free instead of new and delete, obviously). In C++, it is generally preferable to use other memory management idioms like RAII, if you can.

Anemia answered 10/12, 2009 at 15:22 Comment(0)
K
6

Yes it is legal in C++, but doing this is not generally considered as a good practice. It is always better for the class which performed new to delete the same.

Kronfeld answered 10/12, 2009 at 15:22 Comment(2)
I don't see a class "performing a new" anywhere in the given code. You probably meant "block" instead of "class", but that's not always possible or useful.Ophthalmologist
But that class may well perform the deletion using a function that takes a pointer as a parameter.Freer
B
2

Yes, this is perfectly legal. You can delete a pointer from wherever, as long as it points to some object allocated on the heap (or is equal to 0).

Whether the caller expects their object to be deleted by the function, that's another question.

Beforetime answered 10/12, 2009 at 15:21 Comment(0)
H
1

That's completely legal, though in such a case it's probably better to manage memory ownership with something like boost::shared_ptr.

Heterograft answered 10/12, 2009 at 15:24 Comment(0)
E
0

It is perfectly legal to do that. You must make sure that the pointer isn't used in the caller after that point. In general, the name of the function doing the delete should indicate that is what is happening (e.g., contain delete, release, free, etc). Another potential problem is making sure that the data pointed to was allocated with new and not new[].

Ellersick answered 10/12, 2009 at 15:23 Comment(0)
D
0

It is valid and can be very useful when writing a cleanup method for the object, although 9/10 times you'd want to put the cleanup logic into the destructor.

One good reason though to write a separate cleanup would be if you want to keep the object "alive" but not used for awhile, maybe in an array or pool of objects that you pull from occasionally when you need a new one without wanting the constructor overhead.

If you are going to have pointers passed in you should check to make sure they aren't null to avoid any undefined behaviour.

Deflected answered 10/12, 2009 at 15:26 Comment(0)
I
0

Probably a bit late to the discussion, but I wanted to add a clarification: the function only takes a copy of the pointer ( fnc(int* a) is a pass by value) thus you're deleting the local copy of the pointer you've passed and the original pointer will remain available.

That code probably was optimized by the compiler to avoid unnecessary allocation and deletion which allowed it to work.

Intussusception answered 18/6, 2021 at 18:7 Comment(0)
F
0

You realize that you're not actually deleting the pointer passed to the function, right? That initial pointer will 'survive' the deallocation inside delete_test() because you'll only delete a local copy.

#include<iostream>

class test_class{
public:
    test_class():h(9){}
    int h;
    ~test_class(){std::cout<<"deleted";}
};

void delete_test(test_class* pointer_2){
    delete pointer_2;
}

int main(){
    test_class* pointer_1;

    while(true){
        pointer_1 = new test_class;

        //std::cout<<pointer_1->h;

        delete_test(pointer_1);
    }
}
Flatcar answered 27/5 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.