【问题标题】:can a pointer be deleted several times c++?c++可以多次删除指针吗?
【发布时间】:2025-12-06 16:00:01
【问题描述】:

如果我有以下示例:

test.h

class MyClass
{
public:
MyClass();
std::string name1;
std::string name2;
std::string type1;
std::string type2;

void method1(MyClass &obj1);
void method2(MyClass &obj2);
}

test.cpp

MyClass *mainObject = new MyClass();

MyClass::MyClass()
{
}
void MyClass::method1((MyClass &obj1)
{
//do stuff
mainObject=&obj1; //we populate some of the MyClass variables


}
void MyClass::method2((MyClass &obj2)
{
//do stuff
mainObject=&obj2; //we populate the rest of MyClass variables
}

什么时候应该删除 test.cpp 中的 mainObject?我应该创建一个析构函数以便客户端删除它吗?

【问题讨论】:

  • 您的代码没有任何意义。您正在创建一个全局堆分配的MyClass 对象,然后通过非静态成员函数对其进行修改。这是一个巨大的内存泄漏。你想在这里做什么?
  • 我想要一个 MyClass 类的实例,它会在不同方法的编译过程中被修改,并且每次都会更新。所以每次我呼吁一个新方法 mainObect 总是有最后一次更新
  • 代码很可疑。在MyClass::method1 中,您有两个 对象。有obj1,也有*this。从这个角度来看,“一些 MyClass 变量”的评论没有意义。两个对象都有自己的变量。
  • @sunset:但是你涉及到三个对象!你有mainObject指向的对象,你有你正在调用method1()的对象,你有obj1
  • 我应该用 MyClass mainObject 更改 mainObject 指针吗?在这种情况下,我想不会有内存泄漏。对吗?

标签: c++ pointers reference


【解决方案1】:

这是一个很好的例子,最好不要自己考虑。

使用shared_ptr<MyClass> mainObject;(新的 C++11 或 Boost 版本)。它会为你做delete

请注意,method1()method2() 也应该通过 shared_ptr 接受他们的论点。目前,他们正在做一件非常糟糕的事情:删除一个通过引用传递的对象。

【讨论】:

  • 不,他们目前没有删除任何内容。他们所做的是对通过引用传入的对象的生命周期做出疯狂的假设。 (除了语法错误之外。)
  • 目前我没有删除主对象。现在我想优化我的代码。这就是为什么我要求解决方案。谢谢。欣赏。除了使用智能指针还有其他选择吗?
  • @sunset:正如我在回答中所说,重要的是程序逻辑,而不是代码:谁负责该对象?如果那段代码用它完成,则应该删除该对象。不早不晚。当然,所有权也可以传递,但如果没有明确的所有权,重新设计可能是个好主意,而不是对问题扔智能指针魔法并希望它会消失。
  • @sunset:智能指针并不神奇。您可以自己编写等效代码。但是,即使你做对了,它们也很难理解。现有的 shared_ptr<> 行为有据可查。
  • 你能给我一些想法吗?有没有办法不使用智能指针?问题是我需要这个全局对象。我应该有指针:MyClass mainObject;?我需要尽快完成这件事。欣赏!
【解决方案2】:

多次删除指针变量(指向非0)比不删除更糟糕。因为前者会导致难以发现的错误和未定义的行为。

您的代码编写不正确。当您尝试使用&obj1&obj2 分配它时,您应该立即delete mainObject;。但请确保您只是第一次这样做。如果指针指向obj1obj2,请不要delete

我从这个问题和你的previous question 中感觉到你来自Java/C# 背景。最好先读一本关于 C++ 的好书,你会发现大多数时候你不需要new/delete

【讨论】:

  • 除非你每次删除后都将它设置为NULL,否则你可以一直删除它:)
  • 你是什么意思。你应该删除 mainObject;一旦你尝试用 &obj1 或 &obj2 分配它?能给我写个例子吗?
【解决方案3】:

当你使用完指针指向的对象后,你应该删除指针。当指针指向单个对象时,您不应将其删除两次。如果指针指向您未使用 new 动态分配的对象,则不应删除该指针。

【讨论】:

    【解决方案4】:

    我想我会走一条稍微不同的路。

    像这样:

    测试.h

    class MyClass
    {
    public:
      MyClass();
      std::string name1;
      std::string name2;
      std::string type1;
      std::string type2;
    
      void method1(MyClass &obj1);
      void method2(MyClass &obj2);
    }
    

    test.cpp

    MyClass mainObject; // default c-tor called automatically.
    
    MyClass::MyClass()
    {
    }
    void MyClass::method1(MyClass & obj1)
    {
      //do stuff
    
      //we populate some of the MyClass variables
      mainObject.name1=obj1.name1;
      mainObject.type1=obj2.type1;
    }
    void MyClass::method2(MyClass & obj2)
    {
      //do stuff
    
      //we populate more of the MyClass variables
      mainObject.name2=obj1.name2;
      mainObject.type2=obj2.type2;
    }
    

    没有简单的方法可以只填充对象的一部分而不指定哪些部分。

    但是,否则,如果您不使 mainObject 成为指针,那么您就不需要为它分配空间,这是自动完成的。 (但是,除非真的需要,否则我应该反对使用全局变量!)

    我认为你正在尝试做的这种实现将完全避免使用堆,不需要新建/删除。

    【讨论】:

      【解决方案5】:

      任何资源都应该有一个逻辑所有者,并且该所有者应该删除该资源。

      在某些情况下,共享所有权是有意义的,这就是 boost::shared_ptr 和类似解决方案的用途。最后一个放弃所有权的就是删除资源的那个。

      【讨论】:

        【解决方案6】:

        从所有 cmets 看来,您实际上可能想要以下内容:

        static MyClass mainObject; // Not a pointer. Local to test.cpp
        
        void MyClass::method1()
        {
          //do stuff
          mainObject=*this; // Make a copy of the last object modified.
        }
        void MyClass::method2()
        {
          //do stuff
          mainObject=*this; // Make a copy of the last object modified.
        }
        

        这样,无论你调用foo.method1()还是bar.method2.左侧的对象都会复制到mainObject。根本不需要指针时髦,不需要new 也不需要delete

        【讨论】:

          【解决方案7】:

          什么时候应该删除 test.cpp 中的 mainObject?

          不再使用时。

          我应该创建一个析构函数以便客户端删除它吗?

          如果必须释放类 MyClass 的某些资源,您只需要创建一个析构函数 - 显示的代码不是这种情况。您应该释放 (=delete) 的是 mainObject。但无论如何,method1(..) 和 method2(..) 正在覆盖 mainObject 指针,这会导致指针悬空(您无法再访问该对象)。

          [编辑]
          回答你的问题:

          c++可以多次删除指针吗?

          1. 指针通常不会分配给 new - 只有它们指向的对象。
          2. 如果您的意思是“可以在同一个指针上多次调用delete 吗?”答案是否定的,会导致UB。 delete 在零指针上已定义且合法。

          【讨论】:

          • @sunset:为什么要共享 MyClass 对象的状态?根据您的第一条评论,我认为最好传递引用/指针而不是使用共享状态(这会引入很大的隐藏依赖)。 -> 没有静态/全局对象 - 无论是否新。