簡體   English   中英

遞歸C ++調用中的內存分配

[英]Memory Allocation in Recursive C++ Calls

我在遞歸C ++程序中分配和釋放內存時遇到問題。 因此,如果不使用自動內存管理解決方案,我想知道是否有人可以幫我解決我遇到的內存泄漏問題。

以下代碼基本上解釋了問題(盡管這是一個人為的例子,請糾正我所犯的任何錯誤或簡化)。

一個數字類,用於保存數字的值:

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

正如你所看到的那樣,recurse函數中分配的內存被泄露了,但我不確定在哪里可以根據遞歸的性質釋放這些內存?

問題出在這里:

Number& operator + (const Number& n1) const {
    Number result = value + n1.value;
    return result;
};

你通過引用返回一個局部變量( result ),這是一個很大的NO-NO。 局部變量在堆棧上分配,當函數退出時,變量就消失了。 返回對局部變量的引用是將指針返回到現在用於其他東西的堆棧中,這將導致很多不良。

你應該做的是按值返回(只需將返回類型從Number&更改為Number )。 確保您有適當的復制構造函數,或者編譯器自動生成的復制構造函數適合您的需要。 這意味着當operator+返回時,它會生成一個副本(通常可以通過優化),並且由於沒有涉及指針或引用,因此無法獲得損壞的返回值。

要修復內存泄漏,可以使用boost::shared_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;
}

通過僅在堆棧上分配,可以保證在函數返回時清除變量。

否則我認為你必須使用某種智能指針。

所以除了返回Adam Rosenfield指出的局部變量的地址之外,我在代碼中還看到了其他三個問題。

首先,你的恢復功能永遠不會結束。 在recurse()的某個時刻,你必須檢查一個值,使它不再調用recurse()並返回。 這是遞歸的基本部分。 傳遞的參數v1也沒有被使用。

其次,運算符+()實際上不起作用。 沒有辦法將int分配給Number()對象。

第三,在main中傳遞一個名為result的東西,它永遠不會被聲明。

忘記這些錯誤,我假設您要分配堆上的所有對象以避免堆棧溢出,此函數將多次遞歸或者使用的實際對象比Number大得多。 在這種情況下,通過在recurse()內的堆上分配返回變量,您強制調用者刪除返回的對象。 因此,在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

但最大的錯誤是遞歸沒有逃避條款。
這實際上是無限遞歸,基本上會耗盡內存。

聰明的指針是你的朋友。 至少快速閱讀auto_ptr。

另外,請閱讀Adam Rosenfield對您的其他問題的評論(返回對不存在的值的引用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM