2012-02-06 55 views
0

下面的代碼肯定可以運行。我的問題是我在類函數中分配了一些內存並返回一個指向它的指針。但在主函數中,我構建了一個新對象併爲其指定了一個指針。但是如何釋放返回的指針呢?我需要手動去做嗎?如何避免C++中的類函數內存泄漏?

#include "stdio.h" 

class Complex{ 

private: 
    float real; 
    float imaginary; 

public: 
    Complex(float, float); 
    ~Complex(void) {}; 
    void set_real(float r); 
    void set_imaginary(float i); 
    float get_real(); 
    float get_imaginary(); 
    Complex* plus(Complex* another); 
    Complex* minus(Complex* another); 
    Complex* multiply(Complex* another); 
}; 

Complex::Complex(float r, float i){ 
    this->real = r; 
    this->imaginary = i; 
} 

void Complex::set_real(float r) 
{this->real = r;} 

void Complex::set_imaginary(float i) 
{this->imaginary = i;} 

float Complex::get_real() 
{return real;} 

float Complex::get_imaginary() 
{return imaginary;} 

Complex* Complex::plus(Complex* another){ 
    Complex* result = new Complex(0,0); 
    result->set_real(this->real + another->real); 
    result->set_imaginary(this->imaginary + another->imaginary); 
    return result; 
} 

Complex* Complex::minus(Complex* another){ 
    Complex* result = new Complex(0,0); 
    result->set_real(this->real - another->real); 
    result->set_imaginary(this->imaginary - another->imaginary); 
    return result; 
} 

Complex* Complex::multiply(Complex* another){ 
    Complex* result = new Complex(0,0); 
    result->set_real((this->real * another->real) - (this->imaginary - another->imaginary)); 
    result->set_imaginary((this->imaginary*another->real) + (this->real*another->imaginary)); 
    return result; 
} 

int main(int argc, char* argv[]){ 
    Complex* c = new Complex(3,4); 
    Complex* d = new Complex(6,9); 
    Complex* e = new Complex(0,0); 

    //will this line bring memory leak? Because all plus function already build a Complex object on leap. I don't know how to release it since I have to return it. 
    e = c->plus(d); 

    printf("result is %f + i%f", e->get_real(), e->get_imaginary()); 

    delete c; 
    delete d; 
    delete e; 
    return 1; 
} 
+1

我看到一個標題和代碼,哪來的描述。哪裏不對?什麼是錯誤信息?你看到了什麼?你期望看到什麼? – 2012-02-06 19:31:57

+2

你可以避免使用指針嗎? – Karlson 2012-02-06 19:34:26

回答

0

一種方法是使用auto_ptr或類似的智能ptr。

或者,您也可以傳遞到您的加減法,而不是需要被分配的指針結果對象的引用。換句話說,處理類模塊外部的內存。

+0

這裏使用new/delete是多餘的。定期堆棧聲明應該使用不是智能指針。 – luke 2012-02-06 19:35:52

+0

您的替代建議並不比您的第一個建議更好。不要讓Java-C++ prgrammers的情況變得更糟,因爲它們顯示存在一些只是爲他們清理內存的東西,所以無處不在,像在簡單的值類型運算符中那樣垃圾郵件智能指針。 – 2012-02-06 19:40:24

1

由於類僅包含兩個花車,我會傾向於不使用在所有的指針建議(即只返回一個Complex)。

這隻會是8個字節,這是相同的大小(再次,至少在我的系統),其爲指針(至少在我的系統)。

4
Complex* e = new Complex(0,0); 

    //will this line bring memory leak? Because all plus function already build a Complex object on leap. I don't know how to release it 

因爲我必須返回它。 e = c-> plus(d);

是的,它會泄漏。你首先分配e然後你重新分配它指向你的函數返回的任何東西。現在,您首先分配的內存會在空間中丟失而不會被釋放。你應該這樣做:

Complex* e; 
e = e->plus(d); 

再有就是喜歡,你爲什麼要創建plusminus功能,當你真的應該重載operator+operator-等問題。

通過指針返回所有內容都很愚蠢。只需按價值回報。

4

而不是使用所有指針,只是返回值。

Complex* Complex::plus(Complex* another){ 
    Complex* result = new Complex(0,0); 
    result->set_real(this->real + another->real); 
    result->set_imaginary(this->imaginary + another->imaginary); 
    return result; 
} 

變爲:

Complex Complex::plus(const Complex& another){ 
    Complex result(0,0); 
    result.set_real(real + another.real); 
    result.set_imaginary(imaginary + another.imaginary); 
    return result; 
} 
1

刪除所有堆分配,即不使用新的。

變換:

Complex* Complex::plus(Complex* another){ 
    Complex* result = new Complex(0,0); 
    result->set_real(this->real + another->real); 
    result->set_imaginary(this->imaginary + another->imaginary); 
    return result; 
} 

到:

Complex Complex::plus(const Complex& another) const{ 
    Complex result(0,0); 
    result.set_real(this.real + another.real); 
    result.set_imaginary(this.imaginary + another.imaginary); 
    return result; 
} 
+0

@Victor Sehr:我唯一的問題是,當它返回時會產生一個Complex的臨時副本,並且可能效率不高,這取決於調用此方法的次數。如果保存每盎司的速度不是問題,那可能會很好。 或者,可以將參考傳遞給該方法。 – Sid 2012-02-06 19:37:20

+1

它肯定比動態分配內存更快。你只是調整一個Complex大小的堆棧指針,寫一些浮點數,然後可能把它複製到一個寄存器來返回它(假設所有這些都沒有被優化掉)。 – 2012-02-06 19:41:28

+0

@Sid調用'new'肯定會比複製兩個花車慢幾個數量級。 – 2012-02-06 19:44:50

0

的(一個?)的問題是,你分配一個 'e' 指針,然後重新分配後的指針結果的add()。在add函數中,它已經創建了一個新的Complex對象來返回。

所以要解決這個問題,主要你不應該提前分配E.

[或者你可以重組代碼中使用複製/分配過於]

6

是的,你的代碼泄漏瘋狂。如果您絕對需要通過指針返回,則返回std::unique_ptr<Complex>,而不是防漏。但是你的代碼不需要任何指針。

什麼你可能想要的是更多像這樣的:

Complex Complex::operator+(const Complex& another){ //pass by const reference 
    Complex result = Complex(0,0); 
    result.set_real(real + another.real); 
    result.set_imaginary(imaginary + another.imaginary); 
    return result; 
} 

或者更簡單地說:

Complex Complex::operator+(const Complex& another){ 
    return Complex(real + another.real, 
        imaginary + another.imaginary); 
} 

在C++中,我們一般通過與「價值」迴歸的對象或「按常量引用」和不要爲函數參數或返回使用很多指針。指針很容易出錯。按值(和使用operator+)通過允許這樣做:

int main() { 
    Complex c = Complex(3,4); 
    Complex d = Complex(6,9); 
    Complex e = Complex(0,0); 
    Complex e = a + b; //magic! no leaks! 
    printf("result is %f + i%f", e.get_real(), e.get_imaginary()); 
    return 0; 
} 

在不相關的注意事項:

Complex::Complex(float r, float i) 
    :real(r) //faster for some types. This is "more correct" 
    ,imaginary(i) 
{} 

float Complex::get_real() const //const since it doesn't change anything 
{return real;} 

終於,在mainreturn 0表示「一切正常」,並返回任何其他值意味着「什麼出錯了「

+0

太好了。如此豐富!謝謝。我確實是一名java-C++程序員。 – lkahtz 2012-02-06 19:52:25

+0

@ilkahtz:我們可以告訴:D一般來說,不要使用'thing *',而是嘗試使用'std :: unique_ptr '。更安全。 – 2012-02-06 19:53:45

+0

立即檢出文件。驚人的~~! :=) – lkahtz 2012-02-06 20:00:20

1
e = c->plus(d); 

會導致泄漏,因爲由e指向的Complex並沒有在指向新Complex的新指針釋放之前釋放分配。

儘管事實上,該STL有template <typename T> class complex;

#include <complex> 

可以實現算術返回值的成員函數:

Complex Complex::plus(const Complex& another)const{ 
    Complex result(0,0); 
    result.set_real(this->real + another.real); 
    result.set_imaginary(this->imaginary + another.imaginary); 
    return result; 
}