2017-10-16 60 views
0

我正在爲一個CS項目的矩陣類工作,我試圖在構造函數上工作。該項目調用兩個不同的構造函數,一個調用行數和列數,並使其全部爲0,另一個使用初始化程序列表分配值。頭文件到目前爲止是:析構函數立即調用並刪除我的數組

typedef unsigned int uint; 
typedef std::initializer_list<std::initializer_list<double>> i_list; 

class Matrix { 
public: 
double ** arr; 
uint mainRows; 
uint mainCols; 

Matrix(uint rows, uint cols); 
Matrix(const i_list & list); 
Matrix(const Matrix & m); 
~Matrix(); 

}; 

一些測試用例需要你都定義行和使用初始化列表,例如:

Matrix d(2,2); 
d = {{1,2},{3,4}}; 

但我注意到,每一次我嘗試並運行這種代碼,析構函數會立即刪除double ** arr,這是Matrix的值存儲的地方。下面是構造函數的代碼:

Matrix::Matrix(uint rows, uint cols) 
{ 
    mainRows = rows; 
    mainCols = cols; 
    arr = new double*[rows]; 
    for (int i = 0; i < mainRows; i++) { 
     arr[i] = new double[cols]; 
    } 
    for (int i = 0; i < mainRows; i++) { 
     for (int j = 0; j < mainCols; j++) { 
      arr[i][j] = 0; 
     } 
    } 
} 

Matrix::Matrix(const i_list & list) 
{ 
    int i = 0, j = 0; 
    mainRows = list.size(); 
    mainCols = (*list.begin()).size(); 
    arr = new double*[mainRows]; 
    for (std::initializer_list<double> I : list) { 
     j = 0; 
     arr[i] = new double[mainCols]; 
     for (double d : I) { 
      arr[i][j] = d; 
      j++; 
     } 
     i++; 
    } 
} 

Matrix::Matrix(const Matrix & m) 
{ 
    this->arr = m.arr; 
    this->mainRows = m.mainRows; 
    this->mainCols = m.mainCols; 
    for (uint i = 0; i < mainRows; i++) { 
     for (uint j = 0; j < mainCols; j++) { 
      this->arr[i][j] = m.arr[i][j]; 
     } 
    } 
} 

Matrix::~Matrix() 
{ 
    for (uint i = 0; i < mainRows; i++) { 
     delete[] arr[i]; 
    } 
    delete[] arr; 
} 

我猜,因爲它要求同樣的對象兩次它創建了兩個雙** ARS構造,這就是爲什麼析構函數想的刪除原來的,但後來我可以」 t調用其他函數的值。有人能幫我解決我做錯了什麼嗎?

+0

你是否超載'operator ='? – NathanOliver

+0

請創建一個[最小,**完整**和可驗證示例](http://stackoverflow.com/help/mcve)向我們展示。我也建議你花一些時間[閱讀如何提出好問題](http://stackoverflow.com/help/how-to-ask)。當然,請閱讀Eric Lippert的[如何調試小程序](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/),並學習如何使用調試器。 –

+0

如果你沒有,[dudu of this](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)。 – NathanOliver

回答

3

問題是您的複製構造函數只複製源對象的指針,不分配新的內存。

這是問題,因爲

d = {{1,2},{3,4}}; 

創建一個臨時的對象出來{{1,2},{3,4}}。您聲明實際上等於

d = Matrix({{1,2},{3,4}}); 

等於

d.operator=(Matrix({{1,2},{3,4}})); 

在作出轉讓後,您必須指向相同的內存arr兩個對象。然後臨時對象被破壞,導致d內的arr無效,因爲它不再指向分配的內存。

幼稚的解決方案很簡單:分配內存arr指向複製構造函數。 更好的解決方案是停止使用指針和動態分配,而不是使用std::vector,並住the rule of zero,你不需要任何複製構造函數,沒有複製賦值操作符,也不需要析構函數。

1

這是錯誤的:

Matrix::Matrix(const Matrix & m) 
{ 
    this->arr = m.arr; 
    this->mainRows = m.mainRows; 
    this->mainCols = m.mainCols; 
    for (uint i = 0; i < mainRows; i++) { 
     for (uint j = 0; j < mainCols; j++) { 
      this->arr[i][j] = m.arr[i][j]; 
     } 
    } 
} 

注意宥這裏不創造實際的複製。 this->arr = m.arr;使得兩個指針指向內存的相同部分,所以Matrix的新舊實例共享該內存。所以流動for循環什麼都不做。

比其中一個實例被銷燬時,另一個實例指向釋放的內存。

相關問題