为什么这个析构函数不必删除类对象?

时间:2017-01-04 02:23:29

标签: c++ class destructor new-operator delete-operator

我是编程和学习课程的初学者。我正在关注archived online course并为class Polygon制作析构函数。

answer given~Polygon没有要删除PointArray points的行,只包含一行减少numPolygons。 我会假设~PointArray以某种方式被激活以删除points

  • 为什么我们没有delete[] &points;中的~Polygon

  • 如果我的假设是正确的,PointArray的析构函数何时以及如何生效?

  • delete[] &points;中的~Polygon如何影响该计划?

以下简化代码在Visual Studio Community 2015下编译。

谢谢!

class Point {
private: int x, y;
public:
    Point(int x = 0, int y = 0) {
        this->x = x;        // initializes (*this).x with x
        this->y = y;        // initializes (*this).y with x
    }
    // other member functions...
};

class PointArray {
    int len;
    Point *points;
public:
    PointArray() {
        len = 0;
        points = new Point[0];
    }
    PointArray(const Point copyPoints[], const int size) {
        points = new Point[size];
        len = size;
        for (int i = 0; i < size; ++i) points[i] = copyPoints[i];
    }
    PointArray(const PointArray &pv) {
        len = pv.len;
        points = new Point[len];
        for (int i = 0; i < len; ++i) points[i] = pv.points[i];
    }
    ~PointArray() {
        delete[] points;
    }
    // other member functions...
};

class Polygon {
protected:
    PointArray points;
    static int numPolygons; // tracks # of Polygon instances/objects
public:
    Polygon(const Point pointArr[], const int numPoints)
        : points(pointArr, numPoints) {     // initializes internal PointArray
        ++numPolygons;                      // +1 (initialized)
    }
    Polygon(const PointArray &pa)
        : points(pa) {                  // initializes internal PointArray with arg
        ++numPolygons;
    }
    ~Polygon() {
        //delete[] &points;
        --numPolygons;
    }
};

int main() { return 0;  }

1 个答案:

答案 0 :(得分:2)

你的假设基本上是正确的。以下是一些注意事项:

  • delete(和delete[])仅用于使用new运算符将指针删除到堆上分配的变量。在Polygon类中,PointArray成员不是指针,它只是完全包含在Polygon对象中的成员对象。

  • 你是正确的PointArray的析构函数负责删除Point *points类中的PointArray数组。会发生什么,当调用“父”对象(如Polygon)的析构函数时,它会自动递归调用其所有成员对象的析构函数(以及所有他们的成员)对象等)以下是cppreference的相关部分:

  

对于用户定义或隐式定义的析构函数,在执行析构函数体之后,编译器以声明的相反顺序调用类的所有非静态非变体成员的析构函数< / strong>,然后它按照构造的相反顺序调用所有直接非虚基类的析构函数(反过来调用它们的成员及其基类的析构函数等),然后,如果这个对象最多 - 派生类,它调用所有虚拟基础的析构函数。

因此,这个简单案例的顺序是:

  1. 调用~Polygon析构函数并完全执行,递减numPolygons
  2. ~PointArray上调用points析构函数。这将删除PointArray对象拥有的基础数组。
  3. 如果要删除PointArray.points中的~Polygon指针,数组将被删除两次(一次由~Polygon删除,一次被~PointArray删除),这是未定义的行为但可能会导致崩溃。

    编辑添加:作为进一步的评论,在现代C ++中,你可能想要使用像std::unique_ptr这样的“智能指针”,而不是像你的“原始”指针教程正在做。这使你摆脱了这种低级内存管理的负担,因为智能指针类将处理超出范围时删除数组的所有细节。

    第二次修改:@ user4581301有一个更好的建议,就是使用std::vector而不是费心去打扰指针。 vector类将为您处理所有底层内存管理详细信息。它还将动态增长和缩小以处理大小不一的对象数组,而不是被限制为固定大小。