在分配不同的值之前,是否有必要在指针上使用'delete'?

Is it necessary to use 'delete' on pointers before assigning different value?

本文关键字:指针 delete 分配 是否      更新时间:2023-10-16

这可能是一个愚蠢的问题,但我不确定这样做的正确方法是什么(搜索没有为我产生明确的答案)。

考虑下面的代码片段:

class D;
class C
{
    C() {m_Ptr = new D;};
    ~C() {delete m_Ptr;};
    public:
        void setPtr(const D &obj) {*m_Ptr = obj};
    private:
        D *m_Ptr;
};

是可以简单地分配新的值给*m_Ptr,即使它已经指向类D的不同对象?我倾向于使用:

void C::setPtr(const D &obj)
{
    delete m_Ptr;
    *m_Ptr = obj;
}

但我不确定这是必要的还是好的/坏的做法。我的理由是,每个"new"都应该有它的"delete"(或其他释放内存的方法,如Qt中的父子机制)。

谢谢你的澄清!

如果您重新分配指针,则可能需要执行delete。在你的例子中,你不这样做,你只是改变指针指向的数据。

事实上,做某事

delete m_Ptr;
*m_Ptr = obj;

将导致未定义行为,因为在释放指针所指向的内存后对其解引用,然后写入不再"拥有"的内存

还有一个比你现在面临的问题更深层次的问题。

void setPtr(const D &obj) {*m_Ptr = obj};

如何知道obj是否是new创建的对象?如何确保调用者有意让C调用delete的地址?你所做的是糟糕的类设计,有一个更好的解决方案,既解决了你当前的问题,也解决了我所担心的问题。

首先确保你已经阅读了什么是三的规则?

那么,怎样才能使你的类设计得更好呢?使用"三法则"!提供copy(如果可以的话,还有move)构造函数和赋值操作符。完成此操作后,删除setPtrsetPtr是一个坏东西。提供一个构造函数来代替复制一个现有的D对象。通过这种方式,您可以隔离有关如何创建由m_Ptr指向的内容的详细信息。

C(D& d) {m_Ptr = new D(d); };

您还应该为D提供一个适当的复制构造函数。用它来代替

C x;
D* y = new D;
x.setPtr(*D);
你做了

C x = D();
// or
C x;
x = C(D());

您是否希望C根据某些参数保留D ?也许它们是D的构造函数的参数?你可以提供一个"命名构造函数":

class C {
    static C createBlah(int x, float y) {
        C c = D(x, y);
        return c;
    }
};
// Using it...
C c = C::createBlah(42, 3.14f);

所以现在,你的类C的用户不必担心任何有关D的事情。为什么要把负担放在他们身上呢?为什么要让他们使用new,这会让他们陷入严重的危险?为什么要让世界更悲惨?

好了。

UPDATE:让D对象直接作为成员,而不是指向它的指针,这样会更好。@Peter的评论很好地总结了这一点。

每当你有新的东西,你必须删除它。这个规则只有在像std智能指针这样的情况下才会被打破,它会帮你删除内存。

然而,在你的例子中,你只是用在obj的内存填充m_Ptr的内存。因此,删除这里会导致问题。

编辑:正如Peter在评论中所说,在类中存储一个D对象要好得多。尽可能避免这样不必要的指示。