SUN 發問時間: 電腦與網際網路程式設計 · 1 0 年前

[C++]函數內動態宣告用來回傳的值如何delete?

[資料型態宣告]

class matrix {

private:

-- int **mat;

-- int row,col;

public:

-- matrix(const int&a,const int&b);

-- matrix operator+(const matrix &m);

--.....

};

[建構式]

matrix::matrix(const int&a,const int&b) {

--row=a;

--col=b;

--mat=new mtype*[row];

--for(int i=0 ; i<row ; i++)

----mat[i]=new mtype[col];

}

[operator+]

matrix& matrix::operator+(const matrix &m) {

--matrix *ans=new matrix(row,col);

--for(int i=0 ; i<row ; i++) {

----for(int j=0 ; j<col ; j++)

------ans->mat[i][j]=mat[i][j]+m.mat[i][j];

--}

--return *ans;

}

[解構式]

matrix::~matrix() {

--if(mat!=NULL) {

----for(int i=0 ; i<row ; i++)

------delete[] mat[i];

----delete[] mat;

--}

}

為求版面簡潔易讀,將其他程式碼刪除了

想請問的是operator+內使用指標型態的matrix回傳

那ans的記憶體該怎麼delete?

已更新項目:

回月狗大:

你說的我了解也會寫

不過我希望寫的函數以後也能reuse

所以想完整一點

不必每次都改掉A的值

而且我還有寫operator*來做矩陣的相乘

如此必然得用如上的方法才能做

所以還是想知道如何delete

不管如何感謝您的回答^^

2 個已更新項目:

回novus大:

你的答案很棒

讓我學到了新知

既然不能傳回指標

那能否說明一下傳回複本的使用方式和原理呢

在下才疏學淺

希望能多長些知識

拜託囉

2 個解答

評分
  • novus
    Lv 6
    1 0 年前
    最佳解答

    1.除了operator=之外,如果你看到像是

    matrix& matrix::operator┼(const matrix &m) //傳回reference

    不用懷疑,請馬上改掉,這是個不良的設計,除了無有效的方法釋放記憶體,另一方面程式的行為和你想像的有差異。這在C┼┼社群當中已經是個經過充分研究的問題了。

    這才是你所需要的:

    const matrix matrix::operator┼(const matrix &m)

    傳回複本而不要傳回reference!!

    2.如果matrix內部的資料很大,可想而知傳回複本的成本比較高。

    有一些程式設計的技巧,利用類別包裝的手法可以做到copy on write,將複製的成本降到最低。

    3.月狗的解決方法解決了記憶體釋放的問題,但是如此一來operator┼的動作就和內建的┼號不同了。

    如果函數行為和內建的operator不同,那麼最好不要讓函數變成operator的形式,改用像是Add(const matrix &m)之類的會比較好

    2007-05-21 18:28:44 補充:

    最單純的做法:

    const matrix matrix::operator+(const matrix &m) {

    matrix ans(row,col);

    .....

    return ans;

    }

    如此一來我們獲得的只是ans的複本,而ans就可以安心的釋放了。

    但是要特別注意的是,C++只會複製指向陣列的指標成員,而不會複製陣列內容,也就是說ans和複本所指的陣列是同一個。

    依照你的設計,ans在解構的時候也會一併將二維陣列給delete掉,於是複本當中的int **mat不知指向何物。所以你必須在copy constructor和operator=當中利用手工的方式把陣列複製過去。

    2007-05-21 18:41:57 補充:

    上面的做法在記憶體的使用上算是安全的,美中不足的是複製二維陣列有點耗時,對一般性的用途已經可以了。

    解決的辦法之一是,在matrix解構時先檢查mat所指向的陣列是否還被其他人引用,若否才delete陣列,若還有其他人使用就不delete陣列。總之最後使用的人要負責歸還,就不必每次都要將整個陣列複製。

    這可以利用一些設計上的小技巧來達到,有個專有名詞稱為pointer to implementation。詳參:

    http://www.gotw.ca/gotw/028.htm

  • Walala
    Lv 5
    1 0 年前

    Operator + 的部份有點怪怪的(如果我有誤解請原諒), 你的目的應該是要能寫成像 MatrixA=MatrixA+MatrixB的式子吧

    先看右半邊, 你應該是拿A和B的內容來加就可以了, B就是你的參數m, 而A, 應該是用 this 就可以取得, 所以你應該不需要去 new 一個 ans 出來, 所以也就不需要 delete了

    而最後, 把 this return 回去就可以了

還有問題?馬上發問,尋求解答。