什么负责删除我的指针

What is responsible for deleting my pointer?

本文关键字:我的 指针 删除 什么      更新时间:2023-10-16

我经常想知道,

我知道我可以创建一个指向对象实例的指针,同时使用 new 关键字将该指针作为参数传递给函数。就像我在下面的 Animation::newFrame 函数中所做的那样,在下面的示例中给出。

但是,我也知道,作为一般规则,我负责调用delete我使用 new 创建的东西。

因此,当我像这样调用 frame 的构造函数时:

Frame* myFrame
    = new Frame(new point(0,0), new point(100,100), new point(50,20));

最终为我在上述函数调用中使用new创建的 3 个点释放内存的责任在哪里?

毕竟,以上3个新点并没有完全让我delete的名字。

我一直假设它们属于调用它们的函数的范围,并且它们只会超出函数的范围。然而,最近我一直在想也许事实并非如此。

我希望我在这里已经足够清楚了。

提前感谢,

家伙

struct Frame
    {
    public:
        point f_loc;
        point f_dim;
        point f_anchor;
    //the main constructor:: Creates a frame with some specified values
        Frame(point* loc, point* dim, point* anchor)
        {
            f_loc = loc;
            f_dim = dim;
            f_anchor = anchor;
        }
    };
struct Animation
    {
    public:
        vector<Frame*> frameList;
    //currFrame will always be >0 so we subtract 1
        void Animation::newFrame(int &currFrame)
        {
            vector<Frame*>::iterator it;//create a new iterator
            it = frameList.begin()+((int)currFrame);//that new iterator is 
                    //add in a default frame after the current frame
            frameList.insert(
                        it,
                        new Frame(
                            new point(0,0),
                            new point(100,100),
                            new point(50,20)));
            currFrame++;//we are now working on the new Frame
        }
        //The default constructor for animation. 
        //Will create a new instance with a single empty frame
        Animation(int &currFrame)
        {
                frameList.push_back(new Frame(
                    new point(0,0),
                    new point(0,0),
                    new point(0,0)));
                currFrame = 1;
        }
    };

编辑:我忘了提到这个问题纯粹是理论上的。我知道有更好的替代原始指针,例如智能指针。我只是要求加深我对常规指针以及如何管理它们的理解。

此外,上面的例子取自我的一个项目,该项目实际上是 C++/cli 和 c++ 混合的(托管和非托管类(,所以这就是为什么构造器只接受point*而不是按值传递(point(。因为point是一个非托管结构,因此在托管代码中使用时,必须由我自己(程序员(管理。:)

澄清并通常强制执行资源所有权的语义是程序员的责任。 这可能是一件棘手的事情,尤其是在处理原始指针时,在资源所有权尚未得到任何实际设计考虑的环境中。 后者不仅在菜鸟程序员编写的玩具程序中很普遍,而且在具有数十年经验的人编写的生产系统中也很普遍,他们应该更了解。

在上面的实际案例中,Frame对象本身必须负责delete传入的 3 个指针,而Frame本身必须负责delete该指针。

由于资源所有权是一个雷区,程序员很久以前就发明了许多技术来澄清所有权的语义,并使粗心的程序员更难引入错误和泄漏。 如今,C++人们认为最佳做法是尽可能避免原始指针,事实上,完全避免动态分配 - 这在很大程度上是因为资源所有权是一个如此危险的雷区。

在C++中,用于实现这些目标的主要习语是RAII,使用的主要工具是auto_ptr(C++03(,unique_ptrshared_ptr及其同类。 Boost还提供了许多所谓的"智能指针"。 其中许多与 C++11 中的指针相似(事实上,C++11 中的新智能指针是由 Boost 初始开发的(,但也有一些超越了,例如 intrusive_ptr .

首先,需要修复代码以使其编译 - 例如,您可能无法将point*分配给point(取决于point的实现(。

完成此操作后,问题的答案是Animation需要释放其frameList中的所有内容,并且Frame将需要释放传递的point*秒。

一个更好的答案(虽然不是你所要求的(是你应该使用shared_ptrunique_ptr来管理内存 - 这些将为你删除指向的对象。这绝对是我会为frameList做的 - 让它成为std::vector<std::shared_ptr<Frame>>.

在这种情况下,可能没有充分的理由将指针用于 point s(我猜它们只是坐标,复制起来非常便宜( - 我只是通过值或常量引用传递它们。这样就不涉及堆分配,而且要简单得多。

垃圾回收器,智能指针,有时它是自动的(如果您从堆栈中分配(。基本上,负责的是你,但你可以把责任委托给其他地方。

如果您调用的函数没有明确声明它将获得传递的指针的所有权,delete完成后对其进行处理,则您有责任delete您自己new的任何内容。

正如我从您的代码片段中看到的那样,当前的内存策略是"传递所有权"。 例如,您创建 3 个点实例,然后将它们传递给 Frame 构造函数 - 从这一刻起,Frame 实例负责管理这 3 个点内存。因此,这意味着您必须为 Frame 类提供一个析构函数,该析构函数将负责删除存储为成员的 3 个点中的每一个点的内存。

以上所有内容都是关于"原始记忆"技术,这不是必要的新星日。请改用智能指针。例如,std::auto_ptr 在这里是一个很好的候选者(但请注意一些陷阱:如果您将一个auto_ptr复制到另一个,源将被清除为 NULL,目标将拥有内存(。这里另一个广泛分布的候选者是 boost::shared_ptr(它甚至作为 tr1:: 命名空间的一部分包含在最新的 C++ 标准中(。并且不要忘记:您必须了解用于您选择的智能指针的内存策略。否则,您最终将与被摧毁的实例的幽灵交谈,或者您的实例将永远不会像瓶子里的精灵一样被释放。

这在很大程度上取决于约定。 这看起来像是GUI,GUI 中的通常约定是包含对象一旦对delete负责已传递指针。 因此,AnimationdeleteframeList的所有指针都在其析构函数中,以及 Frame将删除它在其析构函数中保存的任何指针。(请注意,此约定非常特定于 GUI,但是,在大多数其他情况下,其他公约将是用过的。

话虽如此,对于一个价值来说,C++也是非常不典型的就像Point要动态分配一样,以及也不会有指向他们的指针。

抱歉,没有完全阅读。您有责任删除刚刚创建的对象,如果您没有对点的引用,则应在框架对象中创建析构函数。http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr380.htm

    class X {
    public:
      // Constructor for class X
      X();
      // Destructor for class X
      ~X();
    };

X::~X(( 在 X 对象删除时自动调用。

如果我错了,请纠正我。