2016-08-24 56 views
4

所以我正在阅读一些关于删除指针参数特别是这些的堆栈溢出答案(1,2),因为我正在构建一个函数,需要一个指针作为参数。我应该删除传递给函数的指针吗?

功能的简化版本低于:

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

没有我感到困惑在这里有什么缺失。例如,如果函数是这样调用的:

Shape * c; 
draw(&c); 

然后我不必删除任何东西。但是,如果是这样的:

draw(new Shape{}); 

然后我必须。所以基本上,我的问题是,如果在参数中使用new关键字,我应该如何去删除。在函数中不会有任何可能的异常,所以不需要RAII。有任何想法吗?请不要提示任何涉及智能指针的事情,因为这是我已经做的事情,这个问题是好奇心。此外,请回答知道该函数可以采用新操作符或现有的指针,基本上意味着我需要一种方法来区分两者。另外,对于我的链接:这些并不真正回答我的问题,因为他们中的大多数只依赖于智能指针或一个呼叫或另一个。

+0

给大家回答:你意识到代码就是一个例子吧?这不是实际的代码,但是(我认为)会生成相同的答案。这不是关于代码,而是真正的删除。 –

+1

我认为答案的立场,不管这个例子。一般来说,没有办法仅仅从一个原始指针告诉对象的生命周期。 – TartanLlama

回答

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

在所有的答案中,这似乎是最直接的,可以理解的。谢谢你! –

2

基本上意思我需要一种方法来区分两者。

不,你不知道。在这种情况下,函数不应该在指针上调用delete。函数的调用者拥有这些信息,如果需要,它应该调用delete指针,而不是函数本身。

+0

你意识到代码就是一个例子吗?这不是实际的代码,但是(我认为)会生成相同的答案。这不是关于代码,而是真正的删除。 –

+2

我明白这是一个例子,答案是一样的 - 不要删除函数内的指针。要么使用智能指针并转移所有权,要么让调用者管理对象。你记住的丑陋的黑客(试图检测内存分配堆栈或堆内存)造成很大的问题,不要这样做。 – Slava

0

简单函数应该会参考指针:

void draw(Shape *&p); 

如果从防止:

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

和:

draw(new Shape()); 
+1

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

1

忽视智能指针或其他RAII解决方案的可能性:它必须被记录在案,作为功能合同的一部分,功能是否需要给定指针的所有权或不。

如果需要所有权,则该功能负责删除它。来电者稍后不得使用它。

您的示例函数名为draw。在这种情况下,我会认为它不应该采取所有权。只需绘制形状并保留即可。

4

没有什么可以说你不能删除一个作为函数参数传递的指针,但通常最好是删除与创建它们相同的上下文中的堆对象。

例如,我会考虑这一点:

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

draw(pShape); 

delete pShape; 

比这更好:

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

后者的例子还可以防止您处理其中的draw()不能调用delete的情况下,任何原因,可能造成内存泄漏。

我强烈建议使用智能指针(例如​​,shared_ptr<>)来处理指针的生命周期。但是,如果您绝对不能,请确保记录您的功能并声明您将指针的所有权交给了您的功能,并且呼叫方在调用draw()后不应期望能够使用pShape

5

现在我对这里感到困惑的是删除。

这正是我们从不将原始指针作为参数传递的原因。

这里有一些经验规则,你可能要考虑:

  1. 你可能不改变形状,我路过你:

    void draw(const Shape& shape);

  2. 你可能会改变形状,但我保留它的所有权:

    void draw(Shape& shape);

  3. 请使用我的形状的副本:

    void draw(Shape shape);

  4. 请把这种形状的所有权离我而去:

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

  5. 让我们分享这种形状:

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

+0

我觉得这个答案非常好,谢谢@RichardHodges,我已经为它加上了书签+1。 –