如何避免C ++中类函数中的内存泄漏?

时间:2012-02-06 19:30:35

标签: c++

以下代码肯定可以运行。我的问题是我在类函数中分配了一些内存并返回指向它的指针。但是在main函数中,我构建了一个新对象并为其指定了指针。但是如何释放返回的指针?我需要手动完成吗?

#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;
}

8 个答案:

答案 0 :(得分: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 ++中,我们通常通过“按值”或“通过const引用”传递和返回对象,并且不会对函数参数或返回使用大量指针。指针容易出错。通过值传递(并使用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;}

最后,在main中,return 0表示“一切正常”并且返回任何其他值意味着“出了问题”

答案 1 :(得分: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->加(d);

是的,它会泄漏。首先分配e,然后重新分配它以指向函数返回的任何内容。现在,您首先分配的内存在空间中丢失,而不会被释放。你应该这样做:

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

然后还有其他一些问题,例如,当你真的应该重载plusminus时,为什么要创建operator+operator-函数。

通过指针返回所有内容是愚蠢的。只是按价值回报。

答案 2 :(得分: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;
}

答案 3 :(得分:1)

由于你的类只包含两个浮点数,我倾向于建议不要使用指针(即只返回一个Complex)。

这只是8个字节(至少在我的系统上),它与指针的大小相同(至少在我的系统上)。

答案 4 :(得分:1)

删除所有堆分配,即根本不使用new。

变换:

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;
}

答案 5 :(得分:1)

e = c->plus(d);

将导致泄漏,因为在指向新Complex的新指针之前,e指向的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;
}

答案 6 :(得分:0)

一种方法是使用auto_ptr或类似的智能ptr。

或者,您也可以在加号或减号方法中传递对结果对象的引用,而不是需要分配的指针。换句话说,处理类模块外的内存。

答案 7 :(得分:0)

(一个?)问题是你正在分配一个'e'指针然后再将指针重新分配给add()的结果。在add函数中,它已经创建了一个要返回的新Complex对象。

所以要解决这个问题,主要的是你不应该提前分配E.

[或者您可以重新构建代码以使用复制/分配]