析构函数导致程序崩溃

时间:2014-12-01 14:45:32

标签: c++ copy-constructor

我真的在使用带有副本构造函数的析构函数的概念。如果我不使用析构函数,代码可以正常工作,就像它自动执行一样。如果我这样做,我会收到一条错误,说“调试断言失败!”和'表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。

但我希望能够理解如何使用析构函数。以下是下面的代码,我非常感谢帮助解释我做错了或者需要做什么!     class Matrix {

private:
    int M;
    int N;
    double *data;

public:
    Matrix();
    int getM() const { return M; }
    int getN() const { return N; }

    //CONSTRUCTOR
    Matrix(int sizeR, int sizeC,double * input_data)
    {
        M = sizeR; //Rows
        N = sizeC; //Columns

        data = new double[M*N]; //creation of 1D array, uses m&n values

        cout << "\nMatrix::Matrix(int sizeR, int sizeC, double * data_value) is invoked...\n\n";

        //ENTER DATA INTO MATRIX HERE:
        for(int i=0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to
            data[i] = input_data[i];//Accesses each value at specific location, inputs value 'val'
        for(int i = 0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";
    }

    //get function uses row and column from user
    double get(int i, int j)
    {
        return data[i*N+j];
    }

    double set(int i, int j, double val)
    {
        data[i*N+j] = val;

        cout << "\n\nNEW MATRIX: ";
        for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";

        return val;
    }

    Matrix(const Matrix& oldMatrix)
    {
        cout¸<< "\nMatrix::Matrix(const Matrix&) is invoked....";
        M = oldMatrix.getM();
        N = oldMatrix.getN();
        data = oldMatrix.data;

        cout << "\n\n";

        //ENTER DATA INTO MATRIX HERE:

        for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";

    }

    //DESTRUCTOR
    ~Matrix()
    {
        //delete data
        delete [] data;
        data = NULL;
        cout << "\n\nMatrix::~Matrix() is invoked...\n\n";
    }



};

int main()
{
    int sizeR, sizeC;
    double val;

    cout << "Enter No. Rows: ";
    cin >> sizeR;

    cout << "Enter No. Columns: ";
    cin >> sizeC;

    double * input_data;


    input_data = new double[sizeR*sizeC];

    //INPUTS VALUES TO ARRAY
    for(int i = 0; i < sizeR*sizeC; i++)//Loops for every row
        input_data[i] = i;

    Matrix M1(sizeR, sizeC, input_data);

    cout << "Enter row that value you are after is in: ";
    cin >> sizeR;
    cout << " & now the column that it is in: ";
    cin >> sizeC;


    cout << "Change value: " << M1.get(sizeR, sizeC) << " to:";
    cin >> val;
    M1.set(sizeR, sizeC, val);

    //calls copy constructor
    M1 = Matrix(M1);
}

3 个答案:

答案 0 :(得分:4)

在复制构造函数中,您复制指针,这意味着您现在有两个具有相同指针的对象。如果其中一个对象被破坏,那么它会使另一个对象的指针无效。

无论如何取消引用此指针,或尝试释放它,都会导致undefined behavior

有问题的问题是这一行:

M1 = Matrix(M1);

该行创建一个临时对象,并将数据从M1复制到该临时对象中,然后将临时对象分配回M1(以及编译器 - 生成的复制赋值运算符只会执行成员的浅表副本,因此与复制构造函数没有太大差别,然后破坏临时对象,导致M1中的杂散和无效指针。


在一个稍微相关的问题上,您可能还想了解the rule of three

答案 1 :(得分:0)

您正在复制构造函数中将一个对象的指针复制到另一个对象:

Matrix(const Matrix& oldMatrix)
{
   ...
   data = oldMatrix.data;

调用复制构造函数后,您有两个对象引用相同的内存块。如果一个对象被破坏,则删除内存块,第二个对象指向无效的内存位置。

在复制构造函数中,您还需要分配一个新缓冲区!

答案 2 :(得分:-2)

解决方案可能是将一个bool变量(例如is_copy)添加到Matrix类中。在构造函数上将其设置为false,在复制构造函数上将其设置为true。如果is_copy为false,则仅在析构函数中释放内存。

或者,正如评论中所建议的那样,最好使用智能指针。