2016-12-12 79 views
1

我試圖在我創建的矩陣類上使用+和=運算符來重載運算符。無論是構造函數還是析構函數都會導致問題,或者它也不是(儘管我將它們中的每一個都變灰了,而且代碼似乎也起作用)。有人能幫助我理解什麼是造成這種奇怪的行爲。當我嘗試創建3個矩陣b和c然後嘗試a = b + c;它只是失敗。構造函數析構函數或對OOP的理解

header file 
#ifndef MATRIX_H; 
#define MATRIX_H; 
using namespace std; 


enter code here 

class matrix 
{ 
friend ostream& operator<< (ostream&, matrix &); 
public: 
    matrix(); 
    matrix(int,int); //constructor 
    matrix(const matrix&);//copy constructor 
    ~matrix(); 
    int getRow(); 
    int getCol(); 
    void setRow(int); 
    void setCol(int); 
    class arr1D{    //proxy class to allow the use of [][]  operator 
     public: 
     arr1D(int* a):temp(a){} 
     int &operator[](int a){ 
      return temp[a]; 
     } 
     int *temp; 
    }; 
    arr1D operator[](int a){ 
    return arr1D(arr2[a]); 
    } 
    matrix& operator=(const matrix&); 

    matrix& operator+(const matrix&); 

protected: 
private: 
    int row , col; 
    int **arr2; 

    }; 

    #endif // MATRIX_H 

enter code here 
cpp file 
#include <iostream> 
#include "matrix.h" 

using namespace std; 

matrix::matrix() 
{ 
setCol(0); 
setRow(0); 
**arr2=0; 
} 


matrix::matrix(int x, int y) //matrix constructor creates x*y matrix and     initializes to 0's 
{ 
setCol(y); 
setRow(x); 
arr2 = new int * [getRow()]; 
if (arr2) { 
    for (int i = 0; i < getRow(); i++) { 
     arr2[i] = new int [getCol()]; 

    }; 
}; 
for (int i=0; i<getRow();i++){ 
    for (int j=0;j<getCol();j++){ 
     arr2[i][j]=0; 
    }; 
}; 
} 

matrix::matrix(const matrix &m){ //defines the copying constructor 
row=m.row; 
col=m.col; 
arr2 = new int*[row]; 
for (int i=0; i<row; i++){ 
    arr2[i] = new int[col]; 
    } 
for (int i=0; i<row; i++){ 
    for (int j=0; j<col; j++){ 
     arr2[i][j] = m.arr2[i][j]; 
    } 
} 

} 

matrix::~matrix(){ //defines the destructor 
for (int i=0; i<row; i++){ 
    delete[] arr2[i]; 
    } 
delete[] arr2; 
} 


int matrix::getRow(){ //getter for row 
return row; 
} 

int matrix::getCol(){ // getter for col 
return col; 
} 

void matrix::setRow(int x){ //setter for row 
row=x; 
} 

void matrix::setCol(int x){ //setter for col 
col=x; 
} 


ostream& operator<< (ostream& output, matrix& a){ 
    int i,j; 
    for (i=0; i < a.getRow() ; i++){ 
     for (j=0; j< a.getCol() ; j++){ 

      output << " " <<a.arr2[i][j]; 

     }; 
     output << "\n"; 
    }; 
return output; 
} 

matrix& matrix::operator=(const matrix& right) 
{ 
if (this == &right) {  // Same object? 
    return *this; 
} 
row = right.row; 
col = right.col; 
for (int i=0; i<row; i++) 
{ 
    for (int j=0; j<col; j++){ 
    arr2[i][j]=right.arr2[i][j]; 
    } 
} 
return *this ; 
} 

matrix& matrix::operator+(const matrix& right) 
{ 
int row=right.row; 
int col=right.col; 
matrix result(row,col); 
for (int i = 0; i < row; i++){ 
    for (int j = 0; j < col; j++){ 
      //cout<<"arr2[i][j]="<<arr2[i][j]<<endl; 
      //cout<<"right.arr2[i][j]="<<right.arr2[i][j]<<endl; 
     result.arr2[i][j]=(arr2[i][j] + right.arr2[i][j]); 
      //cout<<"result.arr2[i][j]="<<result.arr2[i][j]<<endl; 
    }; 
}; 
return result; 
} 
+0

在cpp文件下我突出顯示「//定義了複製構造函數」。也許我宣佈它錯了?我真的在這黑暗中。 –

回答

1

首先,對方的回答中指出,你在你的operator +返回到一個臨時的參考。這是未定義的行爲。

但不是以這種方式寫operator +,你應該做的是寫operator +=代替,然後又在operator +=方面寫operator +。由於程序員所期望+=也爲除了+matrix工作,這是沒有意義的離開了+=

對於operator +=,您將在此情況下返回對當前對象的引用。

所以我們需要做的是在operator +代碼移到operator +=

#include <exception> 
//... 
matrix& matrix::operator+=(const matrix& right) 
{ 
    if(row != right.row || col != right.col) 
     throw std::logic_error("Matrix not the same size"); 

    for (int i = 0; i < right.row; i++) 
    { 
     for (int j = 0; j < right.col; j++) 
      arr2[i][j] += right.arr2[i][j]); 
    } 
    return *this; 
} 

請注意,我們的引用返回到當前矩陣,因爲+=修改當前矩陣。另請注意,我們在發送到+=的非法矩陣上發出異常。這個IMO比返回合法的matrix更有意義。如果矩陣大小不一樣,代碼不應該嘗試返回矩陣。

現在operator +可以寫成的+=方面:

matrix matrix::operator+(const matrix& right) 
    { 
     return matrix(*this) += right; 
    } 

不管你信不信,這就是它。我們所做的只是創建一個臨時矩陣,並用傳入的參數調用+=。正如我們所期望的那樣,我們將這個結果作爲全新的矩陣返回。

另一個問題是賦值運算符。考慮到你已經寫了一個拷貝構造函數和析構函數,並且拷貝構造函數不需要使用賦值操作符,那麼可以使用copy/swap idiom來實現賦值操作符。

#include <algorithm> 
    //... 
    matrix& matrix::operator=(const matrix& right) 
    { 
     matrix temp(right); 
     std::swap(temp.arr2, arr2); 
     std::swap(temp.row, row); 
     std::swap(temp.col. col); 
     return *this; 
    } 

我們在這裏所做的只是創建一個傳入的對象的臨時矩陣,並用當前對象的內容換出其內容。當臨時死亡時,臨時銷燬已換出的舊內容。

這種方法的優點是不僅實現起來非常簡單(只需要調用一堆std::swap),它也是非常安全的。如果在創建臨時矩陣時出現問題,則會引發std::bad_alloc異常,而不會混淆或更改this的任何成員。在給出的其他答案中,在分配新內存之前首先釋放內存的問題可以通過使用上述技術來解決。

+0

在賦值運算符(=)內。你使用矩陣臨時(右);這個操作是否調用複製構造函數?最後 - (* this)是指什麼?到臨時矩陣或左操作符矩陣?再次感謝,即時通訊抱歉,我只是覺得我缺乏對內存中發生的事情的理解。 –

+0

是的,拷貝構造函數在你做'matrix temp(right)時被調用;'這就是copy/swap工作需要拷貝構造函數的原因。 '* this'是當前的矩陣。 – PaulMcKenzie

+0

非常感謝,更有意義! –