为什么这个析构函数不必删除 class 对象?
Why does this destructor not have to delete the class object?
我是编程和学习 类 的初学者。我正在关注 archived online course 并为 class Polygon
.
创建析构函数
answer given 有 ~Polygon
没有删除 PointArray points
的行,只包含减少 numPolygons
的行。
我假设 ~PointArray
以某种方式被激活以删除 points
.
为什么我们在~Polygon
中不必delete[] &points;
?
如果我的假设是正确的,那么PointArray的析构函数何时以及如何生效?
~Polygon
中的 delete[] &points;
对程序有何影响?
以下简化代码在 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; }
你的假设基本正确。这里有一些注意事项:
delete
(和delete[]
)仅用于删除指向堆上分配的变量的指针,使用new
运算符。在Polygon
class中,PointArray
成员不是一个指针,它只是一个完全包含在Polygon
对象中的成员对象。
你是对的,PointArray
的析构函数负责删除 PointArray
class 中的 Point *points
数组。发生的事情是,当调用 "parent" 对象(如 Polygon
)的析构函数时,它会自动递归调用其所有成员对象(以及所有 它们的 成员对象等)这是来自 cppreference 的相关部分:
For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.
所以,这个简单例子中的顺序是:
~Polygon
析构函数被调用并完全执行,递减numPolygons
。
- 在
points
上调用了 ~PointArray
析构函数。这将删除 PointArray
对象拥有的基础数组。
如果你要删除 ~Polygon
中的 PointArray.points
指针,数组将被删除两次(一次被 ~Polygon
一次被 ~PointArray
删除),这是未定义的行为,但可能会导致崩溃。
编辑添加:作为进一步的评论,在现代 C++ 中,您可能希望使用 "smart pointer",如 std::unique_ptr
,而不是"raw" 指针就像您的教程一样。这使您摆脱了这种低级内存管理的负担,因为智能指针 class 将处理超出范围时删除数组的所有细节。
第二次编辑:@user4581301 有一个更好的建议,即使用 std::vector
而不是使用指针。 vector
class 将为您处理所有底层内存管理细节。它还会动态增长和收缩以处理可变大小的对象数组,而不是被限制为固定大小。
我是编程和学习 类 的初学者。我正在关注 archived online course 并为 class Polygon
.
answer given 有 ~Polygon
没有删除 PointArray points
的行,只包含减少 numPolygons
的行。
我假设 ~PointArray
以某种方式被激活以删除 points
.
为什么我们在
~Polygon
中不必delete[] &points;
?如果我的假设是正确的,那么PointArray的析构函数何时以及如何生效?
~Polygon
中的delete[] &points;
对程序有何影响?
以下简化代码在 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; }
你的假设基本正确。这里有一些注意事项:
delete
(和delete[]
)仅用于删除指向堆上分配的变量的指针,使用new
运算符。在Polygon
class中,PointArray
成员不是一个指针,它只是一个完全包含在Polygon
对象中的成员对象。你是对的,
PointArray
的析构函数负责删除PointArray
class 中的Point *points
数组。发生的事情是,当调用 "parent" 对象(如Polygon
)的析构函数时,它会自动递归调用其所有成员对象(以及所有 它们的 成员对象等)这是来自 cppreference 的相关部分:
For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.
所以,这个简单例子中的顺序是:
~Polygon
析构函数被调用并完全执行,递减numPolygons
。- 在
points
上调用了~PointArray
析构函数。这将删除PointArray
对象拥有的基础数组。
如果你要删除 ~Polygon
中的 PointArray.points
指针,数组将被删除两次(一次被 ~Polygon
一次被 ~PointArray
删除),这是未定义的行为,但可能会导致崩溃。
编辑添加:作为进一步的评论,在现代 C++ 中,您可能希望使用 "smart pointer",如 std::unique_ptr
,而不是"raw" 指针就像您的教程一样。这使您摆脱了这种低级内存管理的负担,因为智能指针 class 将处理超出范围时删除数组的所有细节。
第二次编辑:@user4581301 有一个更好的建议,即使用 std::vector
而不是使用指针。 vector
class 将为您处理所有底层内存管理细节。它还会动态增长和收缩以处理可变大小的对象数组,而不是被限制为固定大小。