退货前超出范围

时间:2015-03-18 18:35:55

标签: c++

以下代码段是我在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年多的修补过程中第一次遇到这个问题。

感谢。

2 个答案:

答案 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。