Reputation: 11789
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
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:
You may not alter the shape I am passing you:
void draw(const Shape& shape);
You may alter the shape, but I am retaining ownership of it:
void draw(Shape& shape);
Please use a copy of my shape:
void draw(Shape shape);
Please take ownership of this shape away from me:
void draw(std::unique_ptr<Shape> shape);
Let's share this shape:
void draw(std::shared_ptr<const Shape> shape);
Upvotes: 10
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
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
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
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
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