2013-01-31 22 views
0

解決我怎樣才能返回一個對象,它本身在C++堆中分配空間?

解決方案:提供拷貝構造函數和遵循三個規則。

原來的問題

我執行一類是intervalls的矩陣。 我INTERVALL類看起來像這樣(shortned):

class Intervall 
{ 
friend std::ostream& operator<<(std::ostream& output, const Intervall& i); 

public: 
    Intervall(); 
    Intervall(double n); 

private: 
    double min_value; 
    double max_value; 
}; 

使用這種實現:

Intervall::Intervall(){ 
    min_value = 0; 
    max_value = 0; 
} 

Intervall::Intervall(double n){ 
    min_value = n; 
    max_value = n; 
} 

ostream& operator<<(ostream& output, const Intervall& i){ 
    output << "[" << i.min_value << ", " << i.max_value <<"]"; 
    return output; 
} 

我Matrix類看起來是這樣的:

class IntervallRMatrix 
{ 
friend std::ostream& operator<<(std::ostream& output, const IntervallRMatrix& irm); 

public: 
    IntervallRMatrix(); 
    ~IntervallRMatrix(); 

    void setIdentity(); 

    IntervallRMatrix clone(); 

private: 
    void initialize(); 

    Intervall* data; 
    Intervall** cells; 
}; 

與下面的實現:

IntervallRMatrix::IntervallRMatrix(){ 
    initialize(); 
} 

IntervallRMatrix::~IntervallRMatrix(){ 
    delete cells; 
    delete data; 
} 

ostream& operator<<(ostream& output, const IntervallRMatrix& irm){ 
    output << "3 x 3" << endl; 
    for(int i=0; i<3; i++){ 
     for(int j=0; j<3; j++){ 
      output << irm.cells[i][j]; 
     } 
     output << endl; 
    } 
    return output; 
} 

void IntervallRMatrix::setIdentity(){ 
    cells[0][0] = Intervall(1); 
    cells[1][1] = Intervall(1); 
    cells[2][2] = Intervall(1); 
} 

IntervallRMatrix IntervallRMatrix::clone(){ 
    IntervallRMatrix result; 
    for(int i=0; i<3; i++){ 
     for(int j=0; j<3; j++){ 
      result.cells[i][j] = cells[i][j]; 
     } 
    } 
    return result; 
} 

void IntervallRMatrix::initialize(){ 
    data = new Intervall[9]; 
    for(int i=0; i<9; i++){ 
     data[i] = Intervall(); 
    } 
    cells = new Intervall*[3]; 
    for(int i=0; i<3; i++){ 
     cells[i] = &data[3*i]; 
    } 
} 

這一切都工作正常,直到我使用克隆功能。此代碼生成一個存儲器錯誤:

int main() 
{ 
    IntervallRMatrix m1; 
    m1.setIdentity(); 
    cout << "m1: " << m1 << endl; 

    IntervallRMatrix m2 = m1.clone(); 
    cout << "m2: " << m2 << endl; 
    return 0; 
} 

第一COUT按預期工作。 第二個cout沒有。程序試圖讀取​​時出錯。

如果我沒有在析構函數中刪除cells and data,則不會發生此錯誤。

我以我的方式聲明單元格和數據,因爲我想重載方括號,以便稍後寫入Intervall = Matrix[i][j]。 我也想重載算術運算符,以便我可以編寫Matrix m3 = m2*m1。事實上,我已經這樣做了,那是錯誤發生的地方。

現在,最後我的問題: 我該如何實現一個返回IntervallRMatrix的函數,該函數不會導致內存錯誤,同時仍然能夠釋放析構函數中分配的內存?

+0

除了(或另外)克隆方法外,還應考慮實現複製構造函數和賦值運算符。 –

+0

謝謝,這確實解決了我的問題。 – fholStack

回答

0

這裏的問題是克隆方法返回剛剛在堆棧上創建並初始化的結果對象的副本。 因爲你沒有暗示任何拷貝構造函數(從我們可以看到的),編譯器提供了一個默認的構造函數。這個默認實現將基本上將成員變量從一個實例複製到另一個實例(在這種情況下,指向單元和數據的指針)。內容將不會被複制。 一旦您離開克隆函數作用域,結果對象將被刪除(作爲預解析器代碼),並最終得到一個結果副本,其中單元格和數據指針仍指向空閒內存。這導致了一個未定義的行爲(通常讀作「它會崩潰」)

按照奧利查爾斯沃斯在他的答案中的三條規則。

+0

非常感謝,提供了複製構造函數的技巧。 – fholStack

2

最好的解決方案是避免手動內存管理。使用適當的容器(例如std::vector)或智能指針。

如果你必須做手動管理,那麼確保你按照Rule of Three

+0

謝謝!在使用向量之前,我遇到了其他問題,但提供了三條規則中提到的複製構造函數。 – fholStack

相關問題