簡體   English   中英

C ++,這會導致內存泄漏嗎?

[英]C++, will this cause memory leak?

我知道我無法獲得本地變量的引用。 如:

int& func1()
{
    int i;
    i = 1;
    return i;
}

而且我知道這是正確的,但是在調用func2()之后必須刪除它

int* func2()
{
    int* p;
    p = new int;


       *p = 1;
        return p;
}

int main()
{
    int *p = func2();
    cout << *p << endl;
    delete p;
    return 0;
}

如果函數是這樣的:

MyClass MyFunction()
{
    return new MyClass;
}

MyClass的整個定義是:

class MyClass
{
public:
    MyClass() : num(1){}
    MyClass(MyClass*) : num(10){}
    int num;
};

這會導致內存泄漏嗎?

我應該如何避免呢? 該函數返回的對象不是指針,那么如何刪除它呢?

PS:該代碼來自《 R ++上的書》第10章。原始代碼為:

Picture frame(const Pictrue& pic)
{
    // Picture has a constructor Picture(*P_Node)
    // Frame_Pic derives from P_Node
    // So the constructor Picture(*P_Node) will implicitly convert Frame_Pic to Picture.
    return new Frame_Pic(pic);
}
MyClass MyFunction() 
{     
return new MyClass; 
} 

這實際上是錯誤的。您正在返回一個指針。 所以應該

MyClass* MyFunction()

如果您的功能與我上面提到的一樣,並且在使用后不刪除它,則會泄漏內存。

我應該如何避免呢? 該函數返回的對象不是指針,那么如何刪除它呢?

那是編譯錯誤。因此刪除它的意義不會增加

如果刪除從函數返回的指針,則不會發生內存泄漏。 但是,這很容易出錯,因為這意味着該函數的每個客戶端都必須知道應該刪除該返回值。 使用智能指針(根據語義,可以是shared_ptrunique_ptr )是更好的樣式。

Picture示例也是如此。 如果此對象正確地管理其資源(即在析構函數中刪除並具有良好的副本構造函數和operator= (根據規則 ),則不會發生內存泄漏。

使用具有指針構造函數的更新后的MyClass ,我想您應該編寫:

MyClass MyFunction() {
    MyClass *ptr = new MyClass;
    MyClass retval(ptr);
    delete ptr;   // the dynamically-allocated object isn't needed any more
    return retval;
}

碰巧是異常安全的,因為MyClass的構造函數不能拋出,但是作為一般規則,在不將結果直接放入智能指針的情況下,您實際上絕對不應該調用new

MyClass MyFunction() {
    std::unique_ptr<MyClass>(new MyClass);
    return MyClass(ptr);
}

無論如何,這是一個相當荒謬的情況-如果您要按價值返回,則完全沒有理由調用new

MyClass MyFunction() {
    MyClass tmpvalue;
    return &tmpvalue; // doesn't actually return the pointer, just an object
                      // constructed from it
}

而且由於指針的值甚至沒有被指針構造函數使用,因此您也可以這樣寫:

MyClass MyFunction() {
    return 0; // returns an object constructed from a null pointer
}

在您引用本書的原始代碼中,我猜想Picture類具有一個P_Node*類型的數據成員,該成員在其中存儲指針值,並在其析構函數中對該指針調用delete 希望作者也對Picture的復制構造函數和復制賦值運算符進行一些操作,以防止復制后出現雙重釋放。 我沒有這本書,所以無法檢查我的猜測,但是Picture的代碼應該顯示它是如何完成的。

[編輯:哦,那是Koenig和Moo的書之一。 他們勝任(勝任),所以可以肯定他們的Picture類正確地處理了資源。 如果不是,那是因為這是故意做錯事的例子。]

一個簡單的檢查是這樣的:

  • 如果您在程序中使用Nnew數,則必須在程序中使用N兼容的 1 delete ,以避免內存泄漏2

那你是在做嗎 是的,在第一種情況下(您正在做new int ),您確實做到了。 沒有內存泄漏。

剩下的帖子對我來說還不夠清楚!


1.通過兼容 delete ,我的意思是,如果您以ptr = new T[M]的形式使用new ,那么兼容delete應采用delete []ptr的形式。 同樣, delete ptrptr = new T兼容。

2.當然,如果您使用一些智能指針,則不必顯式使用delete

它與您的“ func2”示例相同。 曾經稱為“框架”的人最終需要釋放返回的圖片。

MyClass MyFunction()
{
    return new MyClass;
}

是錯誤的,因為operator new返回指向MyClass的指針,但是您的函數返回MyClass,而不是MyClass *

暫無
暫無

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

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