I'm a beginner at programming and learning about classes. I'm following an archived online course and making a destructor for the class Polygon.
The answer given has ~Polygon without a line to delete the PointArray points, only containing a line to decrement numPolygons.
I would assume that ~PointArray is activated somehow to delete the points.
Why do we not have to
delete[] &points;in~Polygon?If my assumption is correct, when and how does PointArray's destructor go into effect?
How would having
delete[] &points;in~Polygonaffect the program?
The following simplified code compiles under Visual Studio Community 2015.
Thank you!
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; }
Your assumption is basically correct. Here are a couple of notes:
delete(anddelete[]) are only used to delete pointers to variables allocated on the heap, using thenewoperator. In thePolygonclass, thePointArraymember isn't a pointer, it's just a member object entirely contained within thePolygonobject.You're correct that the destructor for
PointArrayis responsible for deleting thePoint *pointsarray in thePointArrayclass. What happens is that, when the destructor of a "parent" object (likePolygon) is called, it automatically recursively calls the destructors for all of its member objects (and all of their member objects, etc.) Here's a relevant section from cppreference:So, the sequence in this simple case is:
~Polygondestructor is called and is completely executed, decrementingnumPolygons.~PointArraydestructor is called onpoints. This deletes the underlying array owned by thePointArrayobject.If you were to delete the
PointArray.pointspointer in~Polygon, the array would get deleted twice (once by~Polygonand once by~PointArray), which is undefined behavior but will likely result in a crash.Edit to add: as a further comment, in modern C++, you would likely want to use a "smart pointer" like
std::unique_ptr, rather than a "raw" pointer like your tutorial is doing. That frees you from the burden of this kind of low-level memory management, since the smart pointer class will handle all of the details of deleting the array when it goes out of scope.Second edit: @user4581301 has an even better suggestion, which is to use
std::vectorrather than bothering with pointers at all. Thevectorclass will handle all the underlying memory management details for you. It will also dynamically grow and shrink to handle variably-sized arrays of objects, rather than being constrained to a fixed size.