递归C+中的内存分配+;电话 我在一个递归C++程序中分配和释放内存有问题。因此,如果不使用自动内存管理解决方案,我想知道是否有人可以帮助我解决我遇到的内存泄漏问题

递归C+中的内存分配+;电话 我在一个递归C++程序中分配和释放内存有问题。因此,如果不使用自动内存管理解决方案,我想知道是否有人可以帮助我解决我遇到的内存泄漏问题,c++,memory,memory-leaks,recursion,C++,Memory,Memory Leaks,Recursion,下面的代码从本质上解释了这个问题(尽管这是一个人为的例子,但请纠正我所犯的任何错误或简化) 用于保存数字值的数字类: class Number { public: Number() { value = 1; }; Number& operator + (const Number& n1) const { Number result = value + n1.value; return resu

下面的代码从本质上解释了这个问题(尽管这是一个人为的例子,但请纠正我所犯的任何错误或简化)

用于保存数字值的数字类:

class Number {
    public:
        Number() { value = 1; };
        Number& operator + (const Number& n1) const {
            Number result = value + n1.value;
            return result;
        };
        int value;
};
执行递归的两个函数:

Number& recurse(const Number& v1) {
    Number* result = new Number();
    Number one = Number();
    *result = *result + recurse(one);
    return *result;
}

int main(...) {
    Number answer = Number();
    answer = recurse(result);
}
正如您所看到的,在递归函数中分配的内存已泄漏,但我不确定根据递归的性质,从何处释放此内存?

问题在于:

Number& operator + (const Number& n1) const {
    Number result = value + n1.value;
    return result;
};
通过引用返回一个局部变量(
result
),这是一个很大的禁忌。局部变量在堆栈上分配,当函数退出时,变量就消失了。返回对局部变量的引用就是将指针返回到堆栈中,该堆栈现在正用于其他用途,这将导致很多不好的结果

您应该改为按值返回(只需将返回类型从
Number&
更改为
Number
)。确保您有一个合适的复制构造函数,或者编译器自动生成的复制构造函数适合您的需要。这意味着当
operator+
返回时,它会生成一个副本(通常可以通过优化进行复制),并且由于没有涉及指针或引用,因此无法获得损坏的返回值


要修复内存泄漏,可以使用智能指针,如
boost::shared\u ptr
。或者,完全抛弃指针和动态内存,只需从
recurse()

按值返回结果,我不明白为什么要首先在堆上分配内存:

Number& recurse(const Number& v1) {
    Number result;
    Number one;

    // I assume there is a step here to determine if the recursion should stop

    result += recurse(one);
    return result;
}
通过只在堆栈上分配,可以保证在函数返回时清除变量


否则,我认为您必须使用某种智能指针。

智能指针是您的朋友。至少快速阅读一下auto_ptr


另外,请阅读Adam Rosenfield对其他问题的评论(返回对不再存在的值的引用)。

因此,除了返回Adam Rosenfield指出的局部变量的地址之外,我在代码中还看到了其他三个问题

首先,你的复活功能永远不会结束。在recurse()中的某个时刻,您必须检查一个值,该值会导致它不再调用recurse()并返回。这是递归的一个基本部分。传递的参数v1也未被使用

第二,运算符+()实际上不起作用。无法将int赋值给Number()对象

第三,主要是传递一个名为result的东西,它从未声明过

忘记这些错误后,我假设您希望分配堆上的所有对象以避免堆栈溢出,因为此函数将多次递归,或者实际使用的对象比数字大得多。在这种情况下,通过在recurse()内的堆上分配return变量,可以强制调用方删除返回的对象。因此,在recurse()和main()中调用recurse()之后,必须删除返回的值。向调用者指示的约定是返回指针而不是引用。所以recurse()和main()看起来像这样:

Number* recurse(const Number& v1) {
    Number* result = new Number();
    Number one;
    if(v1.value >= 2) {
        Number temp;
        temp.value = v1.value - 1;
        Number* partialResult = recurse( temp ); //capture the object to delete
        *result = *partialResult + one;
        delete partialResult;                    //delete the object
    }
    return result;
}

int main() {    
    Number result;
    result.value = 15;
    Number *answer;
    answer = recurse(result);
    delete answer;
}

注意:递归实际计算的任何内容都是毫无意义的。我不知道目的是什么,但它只是起作用的东西。

动态分配内存有什么原因吗?

Number recurse(const Number& v1) {
    Number result;
    Number one;
    retun result + recurse(one);
}
我还注意到您没有使用v1值

但是最大的错误是递归没有转义子句。

这实际上是一个无限递归,基本上会耗尽内存。

“请更正我所犯的任何错误或简化”--您需要将问题设置为可编辑,以便我们执行此操作。这不是异常安全的。如果您想这样做,请对partialResult使用auto_ptr