Arnav Borborah
Arnav Borborah

Reputation: 11789

Should I delete pointer passed to a function as argument?

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.

Upvotes: 6

Views: 2740

Answers (6)

Richard Hodges
Richard Hodges

Reputation: 69882

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);

Upvotes: 10

Karl Nicoll
Karl Nicoll

Reputation: 16419

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().

Upvotes: 4

michalsrb
michalsrb

Reputation: 4891

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.

Upvotes: 1

Jarod42
Jarod42

Reputation: 217283

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);

Upvotes: 5

fgrdn
fgrdn

Reputation: 91

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());

Upvotes: 0

Slava
Slava

Reputation: 44258

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.

Upvotes: 2

Related Questions