【问题标题】:Should I delete pointer passed to a function as argument?我应该删除作为参数传递给函数的指针吗?
【发布时间】:2016-08-24 13:29:44
【问题描述】:

所以我正在阅读一些关于删除指针参数的 Stack Overflow 答案,尤其是这些(12),因为我正在构建一个需要指针作为参数的函数。

函数的简化版本如下:

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

不,我在这里感到困惑的是删除。例如,如果函数是这样调用的:

Shape * c;
draw(&c);

那我就不用删除任何东西了。但是如果是这样的话:

draw(new Shape{});

那么我必须这样做。所以基本上,我的问题是,如果参数中使用了new 关键字,我应该如何删除。函数中没有可能引发的异常,因此不需要 RAII。有任何想法吗?请不要提出任何涉及智能指针的建议,因为这是我已经要做的,这个问题是好奇。另外,请回答知道该函数可以同时采用新运算符或现有指针,这基本上意味着我需要一种方法来区分两者。另外,对于我的链接:这些并不能真正回答我的问题,因为它们中的大多数只依赖于智能指针,或者一个调用或另一个。

【问题讨论】:

  • 致所有回答的人:您意识到代码是一个示例,对吧?这不是实际代码,而是一个(我认为)会产生相同答案的示例。这不是关于代码,而是真正的删除。
  • 我认为无论示例如何,答案都是有效的。通常没有办法仅从原始指针来判断对象的生命周期。

标签: c++ pointers new-operator delete-operator


【解决方案1】:

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

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

以下是您可能需要考虑的一些经验法则:

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

【讨论】:

    【解决方案2】:

    你可能会使用

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

    【讨论】:

      【解决方案3】:

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

      例如,我会考虑这个:

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

      比这更好:

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

      后一个示例还会阻止您处理 draw() 出于任何原因无法调用 delete 的情况,这可能会造成内存泄漏。

      我强烈建议使用智能指针(例如unique_ptr&lt;&gt;shared_ptr&lt;&gt;)来处理指针的生命周期。但是,如果您绝对不能,请确保记录您的函数并声明您正在将指针的所有权传递给您的函数,并且调用者不应期望在调用 draw() 后能够使用 pShape

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 你知道代码是一个例子吧?这不是实际代码,而是一个(我认为)会产生相同答案的示例。这不是关于代码,而是真正的删除。
        • 我知道这是一个例子,答案是一样的——不要删除函数内部的指针。要么使用智能指针并转移所有权,要么让调用者管理对象。您牢记在心的丑陋 hack(尝试检测内存是否分配在堆栈或堆上)会造成大问题,不要那样做。
        【解决方案5】:

        忽略智能指针或其他 RAII 解决方案的可能性:作为函数合约的一部分,必须记录函数是否拥有给定指针的所有权。

        如果它取得所有权,该函数负责删除它。调用者以后不能使用它。

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

        【讨论】:

          【解决方案6】:

          简单的函数应该期望引用指针:

          void draw(Shape *&p);
          

          如果阻止:

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

          来自:

          draw(new Shape());
          

          【讨论】:

          • 这不会改变任何东西,因为指针可能具有非动态分配对象的地址。
          猜你喜欢
          • 1970-01-01
          • 2019-08-17
          • 1970-01-01
          • 1970-01-01
          • 2012-01-24
          • 1970-01-01
          • 1970-01-01
          • 2021-07-18
          • 2021-08-26
          相关资源
          最近更新 更多