c ++析构函数解除分配问题

时间:2013-11-28 20:51:01

标签: c++ destructor memory-management

我正在尝试编写一个包含double *数组的类,可以通过各种方式填充,在程序结束时,内存应该被释放 - 唉,这不起作用。

我收到“programname.exe已触发断点”的通知,这导致我到main.cpp的最后一行 - 当我删除我的析构函数时它工作正常,所以我假设它必须做与此有关。

以下是相关代码:

·H

    #pragma once
using namespace std;
#include <iostream>
class polynom
{
public:
    polynom(int grad, double* arr);
    polynom(int grad);
    polynom();
    ~polynom(void);
    polynom& operator=(polynom p);
    friend ostream& operator<<(ostream& os, const polynom& p);
private:
    int grad;
    double* arr;
};

的.cpp

polynom::polynom(int grad, double* arr)
{
    this->grad = grad;
    this->arr = arr;
}

polynom::polynom(int grad)
{
    this->grad = grad;
    this->arr = new double[grad];
}

polynom::polynom()
{
    arr = NULL;
}

polynom::~polynom()
{
    delete[] arr;
}

void main()
{
    double arr1[] = {5,0,1};
    double arr2[] = {3,2,1};
    polynom p1 = polynom(2, arr1);
    polynom p2 = polynom(2, arr2);
    system("pause");
}

非常感谢!

2 个答案:

答案 0 :(得分:3)

你正在遇到三级规则。

如果你这样做会有效:

polynom p1(2, arr1);
polynom p2(2, arr2);

问题是你的赋值运算符没有复制数组,因此当你分配本地临时时,它会被立即销毁(与数组一起)。然后,当您的本地人超出范围时,他们会尝试删除已删除的指针。

您应该创建一个复制构造函数operator=,而不是覆盖polynom(const polynom&)。您很少需要覆盖operator=。复制构造函数也更通用 - 它允许您按值传递对象,而operator=仅适用于赋值。

在任何情况下,您都必须分配新数组并复制内容,而不是复制指针。你应该真的使用std::vector,你就不会遇到这些问题。

答案 1 :(得分:2)

在下文中,您将堆栈定义的变量分配给多项式中的arr数组。

double arr1[] = {5,0,1};
double arr2[] = {3,2,1};
polynom p1 = polynom(2, arr1);
polynom p2 = polynom(2, arr2);

一旦多项式被破坏,它就会删除那些指针......你可能不会写这个:

double arr1[] = {1,2,3};
delete arr1;

同样的问题。

---更新

解决问题有两种可能的解决方案:

  1. 接受用户数据的构造函数分配缓冲区并制作副本
  2. 这是最安全的,因为这样对象内的缓冲区被认为是安全的。在非常大的项目中,假设您没有分配数百万个多项式对象,那么从长远来看,这将为您节省大量时间......在这种情况下,慢速可能会成为一个问题。

    1. 构造函数将输入标记为用户输入,这意味着它无权删除它,调用方负责实现此操作
    2. 这可以通过添加布尔标志来实现,如果设置为true(例如),则析构函数不会删除缓冲区。

      但是,这个方法存在一个很大的问题:如果你使用一个基于堆栈的缓冲区并且返回了多项式,那么缓冲区会被return语句删除而你有一个bug ...

      因此我不建议您使用此方法。

      ---附加说明

      你写了polynom(2, arr1); ...请注意你在数组中有三个元素。我建议你改用sizeof():polynom(sizeof(arr1)/sizeof(arr1[0]), arr1);

      另外,正如另一个答案所提到的,你想要重载多项式复制构造函数和复制赋值,因为否则会破坏你的代码。但是,只要你不复制多项式,你就可以了。但是,就目前而言,您最终会使用默认设置,而且根本无法正常工作。