Should I delete pointer passed to a function as argument?
Asked Answered
F

6

6

So I was reading some Stack Overflow answers about deleting pointer arguments particularly these ones(1,2), because I am building a function, that requires a pointer as an argument.

A simplified version of the function is below:

void draw(Shape * b)
{
    //Draws code....
}

No what I am confused about here is deletion. For example, if the function is called like this:

Shape * c;
draw(&c);

Then I don't have to delete anything. But if it is like this:

draw(new Shape{});

then I have to. So basically, my question is, how should I go about deleting if the new keyword is used in the parameter. There are no possible exceptions that could be thrown in the functions, so no need for RAII. Any ideas? Please don't suggest anything involving smart pointers, because that is what I already will do, this question is curiosity. Also, please answer knowing that the function can take both the new operator, or an existing pointer, basically meaning I need a way to differentiate between both. Also, for my links: These don't really answer my question, because most of them just depend on smart pointers, or one call or the other.

Fernandafernande answered 24/8, 2016 at 13:29 Comment(2)
To everyone answering: You realize that the code was an example right? This isn't actual code, but an example that(well I thought) would generate the same answers. It isn't about the code, but really the deletion.Fernandafernande
I think the answers stand regardless of the example. Generally there's no way to tell the lifetime of an object just from a raw pointer.Bootblack
M
5

You might use

void draw(std::observer_ptr<Shape> shape)

or

void draw(Shape& shape)

over

void draw(Shape * shape)

To be explicit that draw doesn't reclaim ownership.

and use smart pointer in signature when you reclaim it.

void Take(std::unique_ptr<Shape> shape);

or

void Take(std::shared_ptr<Shape> shape);
Marseillaise answered 24/8, 2016 at 13:40 Comment(0)
O
9

Now what I am confused about here is deletion.

This is precisely why we never pass raw pointers as arguments.

Here are some rules of thumb you may want to consider:

  1. You may not alter the shape I am passing you:

    void draw(const Shape& shape);

  2. You may alter the shape, but I am retaining ownership of it:

    void draw(Shape& shape);

  3. Please use a copy of my shape:

    void draw(Shape shape);

  4. Please take ownership of this shape away from me:

    void draw(std::unique_ptr<Shape> shape);

  5. Let's share this shape:

    void draw(std::shared_ptr<const Shape> shape);

Overburdensome answered 24/8, 2016 at 14:11 Comment(0)
M
5

You might use

void draw(std::observer_ptr<Shape> shape)

or

void draw(Shape& shape)

over

void draw(Shape * shape)

To be explicit that draw doesn't reclaim ownership.

and use smart pointer in signature when you reclaim it.

void Take(std::unique_ptr<Shape> shape);

or

void Take(std::shared_ptr<Shape> shape);
Marseillaise answered 24/8, 2016 at 13:40 Comment(0)
M
4

There is nothing to say that you can't delete a pointer passed as a function parameter, but generally it is preferred to delete heap objects in the same context that they were created.

For example, I would consider this:

Shape * pShape = new Shape(...);

draw(pShape);

delete pShape;

to be better than this:

draw(new Shape(...));  // Did the shape get deleted? Who knows...

The latter example also prevents you from handling the case where draw() cannot call delete for any reason, potentially creating a memory leak.

I would highly recommend the use of smart pointers (e.g. unique_ptr<>, shared_ptr<>) to handle the lifetime of your pointer. But if you absolutely can't, make sure that you document your function and state that you are passing ownership of the pointer to your function, and that the caller should not expect to be able to use pShape after calling draw().

Marquess answered 24/8, 2016 at 13:41 Comment(0)
W
2

basically meaning I need a way to differentiate between both.

No you do not. In this case function should not call delete on the pointer at all. Caller of the function has this information and it should call delete on the pointer if necessery, not function itself.

Willywilly answered 24/8, 2016 at 13:39 Comment(2)
You realize that the code was an example right? This isn't actual code, but an example that(well I thought) would generate the same answers. It isn't about the code, but really the deletion.Fernandafernande
I understand that this is an example and answer is the same - do not delete pointer inside the function. Either use smart pointers and transfer ownership or let caller manage object. Ugly hacks that you keep in mind (try to detect if memory allocate on stack or heap) create big problems, do not do that.Willywilly
B
1

Ignoring the possibility of smart pointers or other RAII solution: It must be documented, as part of the function contract, whether the function takes the ownership of the given pointer or not.

If it takes the ownership, the function is responsible of deleting it. The caller must not use it later.

Your example function is called draw. In that case I would assume it shouldn't take the ownership. Just draw the shape and leave it be.

Balmoral answered 24/8, 2016 at 13:40 Comment(0)
I
0

simply function should expect reference to pointer:

void draw(Shape *&p);

if prevents from:

Shape shape; // not pointer
draw(&shape);

and from:

draw(new Shape());
Ious answered 24/8, 2016 at 13:39 Comment(1)
This does not change anything as pointer may have address of non dynamically allocated object.Willywilly

© 2022 - 2024 — McMap. All rights reserved.