以下代码段是我在visual studio中遇到的问题的简化版本。
代码在
期间进入析构函数return temp;
调试单步执行。
代码:
class point2d
{
public:
int x, y;
};
class poly2d
{
public:
void operator=(const poly2d& temp)
{
for (cnt = 0; cnt < pointNum; ++ cnt)
{
p[cnt].x = temp.x;
p[cnt].y = temp.y;
}
}
poly2d(int size);
~poly2d();
point2d* p;
int pointNum;
};
poly2d::poly2d(int size)
{
pointNum = size;
p = new point2d[size];
}
poly2d::~poly2d()
{
if (p)
{
delete[] p;
p = 0;
}
}
poly2d copy();
int main()
{
poly2d myPoly(5);
myPoly = copy();
return 1;
}
poly2d copy()
{
poly2d temp(5);
return temp;
}
我知道这件作品毫无意义,但它已经简化并脱离了背景,但同时突出了我的问题。析构函数在return语句之前执行。接下来是复制构造函数,然后是析构函数。它被删除两次,显然会导致错误。这是我在6年多的修补过程中第一次遇到这个问题。
感谢。
答案 0 :(得分:1)
您可以尝试实施三/五规则,但我建议您选择Rule of Zero。它基于以下原则:
具有自定义析构函数,复制/移动构造函数或类的析类 复制/移动分配操作员应专门处理所有权。 其他类不应该有自定义析构函数,复制/移动 构造函数或复制/移动赋值运算符。
您可以将代码简化为以下内容:
struct point2d
{
int x, y;
};
struct poly2d
{
poly2d(std::vector<point2d>::size_type size);
std::vector<point2d> p;
};
该向量将自动处理复制和内存管理,无需额外的工作。示例构造函数如下所示:
poly2d(std::vector<point2d>::size_type size)
: p(size)
{
}
答案 1 :(得分:0)
您没有为类poly2d定义复制赋值构造函数。在这种情况下,您的编译器将为您生成默认构造函数。所有这些构造函数都复制了类的每个字段。
这尤其意味着复制指针point2d * p,而不是基础点。
那么当你调用copy()时会发生什么?
生成新的poly2d,即调用poly2d构造函数。这会产生一个新的point2d。现在你对copy()的调用已经完成。实际分配给你的poly2d myPoly是你的临时对象的副本。一旦对copy()的函数调用完成,就会调用temp对象的析构函数。这个析构函数会破坏临时对象所指向的point2d对象。现在的麻烦是,在任何时候都没有为myPoly创建一个新的point2d对象。 myPoly有一个指向temp指向的对象的指针,现在已经被删除了。那当然很糟糕。
您可以通过定义自己的复制/复制赋值构造函数并确保每次复制poly2d时创建新的point2d来解决这个问题。或者,如已经建议的那样,您可以改为使用std :: vector。