C++ 析构函数导致程序崩溃

C++ 析构函数导致程序崩溃,c++,copy-constructor,C++,Copy Constructor,我真的很难理解将析构函数与复制构造函数结合使用的概念。如果我不使用析构函数,代码工作正常,因为它会自动执行。如果我这样做,我会得到一个错误,说“调试断言失败!”和“表达式:\块\类型\有效(pHead->nBlockUse) 但我想了解如何使用析构函数。这是下面的代码,我将非常感谢帮助解释我做了什么错误或需要做什么 类矩阵{ private: int M; int N; double *data; public: Matrix(); int getM()

我真的很难理解将析构函数与复制构造函数结合使用的概念。如果我不使用析构函数,代码工作正常,因为它会自动执行。如果我这样做,我会得到一个错误,说“调试断言失败!”和“表达式:\块\类型\有效(pHead->nBlockUse)

但我想了解如何使用析构函数。这是下面的代码,我将非常感谢帮助解释我做了什么错误或需要做什么
类矩阵{

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);
}
private:
int M;
int N;
双*数据;
公众:
矩阵();
int getM()常量{return M;}
int getN()常量{return N;}
//建造师
矩阵(int sizeR、int sizeC、双*输入数据)
{
M=sizeR;//行
N=sizeC;//列
data=new double[M*N];//创建1D数组,使用M&N值

cout在复制构造函数中复制指针,这意味着您现在有两个对象都具有相同的指针。如果其中一个对象被解构,那么另一个对象将保留一个无效指针

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

有问题的一行是:

M1 = Matrix(M1);
该行创建一个临时对象,并将数据从
M1
复制到该临时对象中,然后将临时对象分配回
M1
(编译器生成的复制赋值操作符将只对成员进行浅层复制,与复制构造函数没有太大区别)然后销毁临时对象,导致
M1
中的指针丢失且无效



关于一个稍微相关的问题,您可能还想了解。

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

Matrix(const Matrix& oldMatrix)
{
   ...
   data = oldMatrix.data;
调用复制构造函数后,有两个对象引用同一个memoryblock。如果一个对象被破坏,则内存块将被删除,第二个对象指向无效的内存位置


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

解决方案可能是向矩阵类添加一个bool变量(
例如is\u copy
)。在构造函数中将其设置为false,在复制构造函数中设置为true。只有在is\u copy为false时才解除析构函数中的内存分配


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

有多少次是
new[]
被调用?有多少次是
delete[]
被调用?设置
data=oldMatrix。复制构造函数中的data1
看起来非常可疑!!!仅供参考,它是析构函数,而不是解构函数。我还对代码进行了一点缩进和解构。不要害怕空白。
data
应该是
vector
,不要使用原始指针这不是解决方案-它只会增加更多问题。如果第一个对象被销毁,但副本仍然存在怎么办?使用布尔标志无法解决所有权和间接寻址问题。这就是为什么我说“可能”。有时,您希望进行浅层复制,而不能简单地通过引用传递矩阵。如果您的原始对象打算在整个程序执行过程中存活下来,则没有problem@NoelPerezGonzalez智能指针可以解决这个问题,正如@WojtekSurowka所说,布尔值不能解决它。
std::shared\u ptr
boost::shared_ptr
。然而,我只会在数据为
const
@tilart时使用这种共享方法。你是对的。还有很多次(比如CUDA)在这里,你不能使用智能指针。但是这超出了问题的范围。“NoelPrErgZZalez我不认为应该使用这样的解决方案。在正常的C++用法中,复制对象是安全的,或者复制是不允许的。你提出一个只有在特殊情况下才能工作的技巧,当某人添加时,就要自找麻烦。s是一个返回对象的函数。只有在需要时才应使用此类技巧,即使这样也不应像您建议的那样隐藏。请使用另一个函数而不是复制构造函数,或者以其他方式使缓冲区共享更为明显,使其显式化。我可以建议改为使用零规则吗