4

这只是出于好奇,因为除了最基本的用途外,我没有在 c++ 中使用过new和。delete

我知道这delete会释放内存。我想知道的是它如何处理更复杂的情况?

例如,如果我有一个这样的用户定义类:

class MyClass
{
public:
    MyClass();
    ~MyClass()
    {
        delete [] intArray;
    }
    //public members here
private:
    int* intArray;
};

假设该类以某种方式为 分配内存intArray,然后在析构函数中释放它,如果我像这样使用该类会怎样:MyClass* myClass = new MyClass();并稍后释放它delete myclass;

如何delete处理所有内存的释放?是否首先调用类析构函数来释放类分配的所有内存(即int* intArray),然后释放分配给类的内存?

如果我有这样的课怎么办:

class MyClass
{
public:
    MyClass();
    ~MyClass()
    {
        delete anotherMyClass;
    }
    //public members here
private:
    MyClass* anotherMyClass;
};

假设anotherMyClass没有分配构造函数,这会很快耗尽内存,如果有一个 MyClasses 链像链表一样相互连接怎么办?在这种情况下,析构函数中的删除语句会起作用吗?当析构函数被调用时,每个都会anotherMyClass被递归释放吗?

您所知道的newand语句是否有任何特定的奇怪技巧或警告?delete

4

2 回答 2

10

p给定一个指向动态分配对象的指针 ( ),delete它会做两件事:

  1. 它调用动态分配对象的析构函数。请注意,~MyClass()完成后,将调用任何类类型成员变量的析构函数。
  2. 它释放动态分配的对象占用的内存。

它不会在对象的成员变量中搜索其他指向 free 的指针;它不会释放任何其他内存,也不会做任何其他事情。

如果需要释放 指向的内存intArray,则需要delete在 的析构函数中将其释放MyClass

但是,在几乎所有 C++ 代码中,您无需担心这一点。您应该使用 、 、 和 等智能指针shared_ptrunique_ptr自动auto_ptr管理scoped_ptr动态分配的对象。手动资源管理充其量是困难的,应尽可能避免。

这是更广泛的成语“范围绑定资源管理”(SBRM,也称为资源获取即初始化或 RAII)的一部分。这是迄今为止在 C++ 代码中任何地方都需要理解和使用的最重要的设计模式。

如果在您的班级中您已经声明了这一点:

boost::scoped_ptr<int> intArray;

然后当scoped_ptr<int>对象被销毁时,它将释放它持有的指针。然后,您不必做任何工作来手动销毁该对象。

在编写良好的现代 C++ 代码中,您应该很少需要手动使用delete. 应该使用智能指针和其他 SBRM 容器来管理需要清理的任何类型的资源,包括动态分配的对象。


在您的第二个示例中,给定一个如下所示的链表:

x -> y -> z -> 0

您将有一个如下所示的操作顺序:

delete x;
  x.~MyClass();
    delete y;
      y.~MyClass();
        delete z;
          z.~MyClass();
            delete 0;
          [free memory occupied by z]
      [free memory occupied by y]
  [free memory occupied by x]

链表中的对象将以相反的顺序销毁。

于 2010-11-23T21:14:41.800 回答
1
delete intArray;

我假设intArray指向int数组的第一个元素?在这种情况下,会delete intArray产生未定义的行为。如果你分配 via new[],你必须释放 via delete[]

delete[] intArray;

是的,我知道,在某些编译器选项下的某些编译器版本的某些系统上似乎可以正常工作——或者它可能delete intArray 不会这对你来说是未定义的行为

此外,您应该遵循三法则。定义自己的析构函数但依赖隐式定义的复制构造函数和复制赋值运算符是灾难的根源。

于 2010-11-23T21:39:23.093 回答