【问题标题】:Deleting objects删除对象
【发布时间】:2012-12-16 08:27:15
【问题描述】:

我是新手,只是想问一个关于删除对象的快速问题。

我有一个名为 MyClass1 的对象,从中我还有许多其他类,MyClassA、MyClassB 等。

现在我应该在 MyClass1 中执行此操作:

MyClass1::~MyClass1()
{

delete MyClassA;
delete MyClassB;

}

或者当我删除 MyClass1 时会自动删除 MyClass1 中创建的所有内容吗?

另外,如果我在 MyClassA 和 MyClassB 中创建了更多对象,是否也必须在各自的类中手动删除这些对象?

谢谢

【问题讨论】:

  • MyClass1 是一个而不是一个对象。你不能delete类,你可以delete一个object的指针。
  • 为什么这个问题被标记为 Qt 的?这是典型的 C++ 问题。

标签: c++ pointers new-operator


【解决方案1】:

仅当您使用 new 运算符创建对象时才调用 delete 运算符

struct  MyClass1
{
  MyClassA mA;
  MyClassB * mB;

  MyClass1()
  {
    mB = new MyClassB;
  }

  ~MyClass1()
  {
    delete mB;
  }
};

【讨论】:

  • 好的,我创建了一个新页面。该页面上有许多按钮。我是否只需要删除页面或所有按钮?
  • 见“三法则”——你的例子有缺陷。
  • @user1013512:Qt 作为一种特殊的方式来管理内存,如果您通过将页面实例作为参数传递来创建 QPushButton,那么您不必为 QPushButton..Qt 调用 delete将为您删除它们
  • 如果你在构造函数中调用new[或者在类中的其他地方没有在同一个函数中被相应的删除],你应该使用delete。如果您的按钮不是用 new [或调用 new] 创建的,那么您不需要 delete 他们 [当然并不意味着您可能不需要做“某事”来清理它们,例如“从屏幕上注销我的按钮”或类似的......]
  • @LuchianGrigore 从他的 cmets 看来,他正在处理 GUI 组件。在这种情况下,他应该禁止复制和分配,而不是担心如何实现它们。
【解决方案2】:

如果你问这个,你只是在学习 C++,所以最好的建议是 - 两者都不是。您应该了解这些内容(动态分配和内存管理 - 请参阅 Guillaume 对此的回答),但您真正应该做的 是使用 RAII(google this)。正确的 C++ 方法是:

struct  MyClass1
{
  MyClassA mA;
  std::shared_ptr<MyClassB> mB;

  MyClass1() : mB(new MyClassB)
  {

  }
};

看到了吗?不再需要析构函数,这意味着您也不需要复制构造函数或复制赋值运算符(这是 Guillaume 的答案存在缺陷的地方 - 它缺少最后两个)。

【讨论】:

  • 对于一般的 c++ 来说这是真的......但是,您是否知道使用 shared_ptr 进行自动内存管理是否与 Qt 的父子层次结构很好地配合 delete父母被摧毁时的孩子? (This question/answer 有更多关于内存管理和 Qt 的信息。)
  • @tmpearce 不熟悉 Qt,但我假设它有据可查。
  • 一般来说,无论如何你都不应该动态分配东西。如果shared_ptr 有效,则可能不应该动态分配对象以开始(这意味着您不需要shared_ptr)。也有例外,但任何使用 shared_ptr 的东西都确实有点高级 C++,不适合初学者。
【解决方案3】:

您不能删除不是指针的对象,因为这不是delete 的目的。它旨在释放与对象关联的动态内存。也就是说,必须删除使用new 创建的任何内容。您可以拥有指向类的指针,并且它们可以被删除。但由于new 没有分配任何内容,因此无需使用delete。实际上,该类将在创建它的范围结束时从内存中销毁。这些对象在堆栈上分配,而动态内存在堆上。堆栈上的对象具有自动存储持续时间(在其范围末尾删除,除非其声明为static,在这种情况下它具有"static" storage duration);此外,堆上的对象具有动态存储持续时间。 C++ 中的动态内存由您控制,这就是我们得到newdelete 的原因(因为C++ 希望我们自己处理内存)。否则删除不是用new 构造的对象是未定义的行为,可能会导致崩溃。

【讨论】:

    【解决方案4】:

    delete 应用于对象,而不是。通常,仅当您调用new 来创建对象时,才需要调用delete(或安排通过共享指针或通常使用RAII 习惯用法自动调用它)。例外情况是某些(库?)调用的返回值是(库的?)文档明确声明调用者必须使用delete 处理的对象(在这种情况下,将调用视为围绕new 已由您负责。)当然,应尽可能避免使用此类 API。

    【讨论】:

      【解决方案5】:

      如果是 Qt,请使用 QPointer!它是一个智能指针:在析构函数中不需要任何东西。

      #include <QPointer>
      
      class MyClass1
      {
        QPointer<MyClassA> pA;
        QPointer<MyClassB> pB;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-26
        • 1970-01-01
        • 2012-09-14
        • 2014-08-14
        • 2011-06-06
        • 2016-01-03
        • 1970-01-01
        相关资源
        最近更新 更多