2012-02-06 100 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; 
}