簡體   English   中英

析構函數導致程序崩潰

[英]Destructor causes the program to crash

我真的在將析構函數與復制構造函數一起使用的概念感到困惑。 如果我不使用析構函數,則代碼會正常工作,因為它會自動執行。 如果這樣做,我會收到一條錯誤消息,提示“調試斷言失敗!”。 和'Expression:_BLOCK_TYPE_IS_VALID(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);
}

在復制構造函數中,您將復制指針 ,這意味着您現在擁有兩個具有相同指針的對象。 如果這些對象之一被破壞,那么它將使另一個對象現在具有無效的指針。

無論如何取消引用該指針或嘗試釋放它,都將導致未定義的行為

有問題的一行是這一行:

M1 = Matrix(M1);

該行創建一個臨時對象,然后將數據從M1復制到該臨時對象中,然后將臨時對象分配回M1 (並且編譯器生成的復制分配運算符將對成員進行淺表復制,因此不需要太多操作(與復制構造函數不同),然后破壞臨時對象,導致M1的雜散指針和無效指針。


在一個稍微相關的問題上,您可能還想了解三個規則

您正在將一個對象的指針復制到Copy構造函數中的另一個對象中:

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

調用復制構造函數后,您將擁有兩個引用同一內存塊的對象。 如果一個對象被破壞,則刪除存儲塊,第二個對象指向無效的存儲位置。

在復制構造函數中,您還需要分配一個新緩沖區!

一種解決方案是在您的Matrix類中添加一個布爾變量(例如is_copy )。 在構造函數上將其設置為false,在復制構造函數上將其設置為true。 如果is_copy為false,則僅在析構函數中釋放內存。

或者,如注釋中所建議,最好使用智能指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM