我应该删除作为参数传递给函数的指针吗?

6

我正在阅读一些关于删除指针参数的Stack Overflow答案,特别是这些答案(1,2),因为我正在构建一个需要作为参数的指针的函数。

以下是该函数的简化版本:

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

我现在困惑的是删除操作。例如,如果函数被这样调用:
Shape * c;
draw(&c);

那么我就不需要删除任何东西。但如果情况是这样的:

draw(new Shape{});

我的问题是,如果在参数中使用 new 关键字,我应该如何进行删除。这些函数不会引发任何异常,因此不需要 RAII。有什么想法吗?请不要建议使用智能指针,因为我已经打算这样做了,这只是我的好奇心。同时,请知道该函数既可以使用 new 操作符,也可以使用现有指针,基本上意味着我需要一种区分两者的方法。对于我的链接:它们并不能解答我的问题,因为大部分都依赖于智能指针或某个调用。


回答的各位:你们意识到这段代码只是一个例子,对吧?这不是真正的代码,而是一个(我认为)会生成相同答案的示例。重点不在于代码,而在于删除操作。 - Arnav Borborah
1
我认为答案不受示例影响。通常情况下,无法仅通过原始指针确定对象的生命周期。 - TartanLlama
6个回答

9
现在我对删除操作感到困惑。
这就是为什么我们从不将原始指针作为参数传递的原因。
以下是您可能需要考虑的一些经验法则:
1. 您不能更改我传递给您的形状: void draw(const Shape& shape);
2. 您可以更改形状,但我仍保留所有权: void draw(Shape& shape);
3. 请使用形状的副本: void draw(Shape shape);
4. 请从我手中获取此形状的所有权: void draw(std::unique_ptr shape);
5. 让我们共享此形状: void draw(std::shared_ptr shape);

5

您可能会使用

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

或者

void draw(Shape& shape)

结束

void draw(Shape * shape)

明确表示draw不会收回所有权。

在重新获取所有权时,请在签名中使用智能指针。

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

或者

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

4

没有任何规定说你不能删除作为函数参数传递的指针,但通常最好在创建堆对象的上下文中删除它们。

例如,我会考虑这样做:

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

draw(pShape);

delete pShape;

要比这更好:

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

后面的例子还可以避免处理draw()由于任何原因无法调用delete的情况,从而可能导致内存泄漏。
我强烈建议使用智能指针(例如unique_ptr<>、shared_ptr<>)来处理指针的生命周期。但如果您绝对不能使用智能指针,请确保记录您的函数并声明您正在将指针的所有权传递给您的函数,并且在调用draw()后,调用者不应该期望能够使用pShape。

2
基本意思是我需要一种区分两者的方法。
不需要。在这种情况下,函数根本不应该调用指针的删除操作。函数的调用者拥有这些信息,如果需要,应该自行调用指针的删除操作,而不是由函数本身来处理。

你意识到这段代码只是一个例子,对吧?这不是真正的代码,而是一个例子,我认为它会生成相同的答案。重点不在于代码,而在于删除操作。 - Arnav Borborah
2
我明白这只是一个例子,答案是一样的 - 不要在函数内删除指针。要么使用智能指针并转移所有权,要么让调用者管理对象。记住丑陋的黑客技巧(尝试检测内存是否分配在堆栈或堆上)会带来很大的问题,不要这样做。 - Slava

1
忽略智能指针或其他RAII解决方案的可能性:作为函数合同的一部分,必须记录函数是否接管给定指针的所有权。
如果它接管了所有权,则函数负责删除它。调用者不能在以后使用它。
您的示例函数名为draw。在这种情况下,我会假设它不应该接管所有权。只需绘制形状并离开即可。

0

简单的函数应该接受指针的引用:

void draw(Shape *&p);

if语句可以防止:

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

以及从:

draw(new Shape());

1
这并不会改变任何东西,因为指针可能具有非动态分配对象的地址。 - Slava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接