簡體   English   中英

*新總是錯的。 總是

[英]*new is always wrong. ALWAYS

為了解釋這個問題中的指針和引用我編寫了這段代碼。

MyClass& MyClass::MyInstance()
{       
    static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
    return myLocalVariable ;
}

其中一個評論,由一個真正令人印象深刻的高聲譽SO用戶,簡單地說: *新總是錯誤的。 總是。

這是我第一次被告知這個問題:它是一個我們都應該知道的着名編碼標准嗎? 背后的原因是什么?

我通常很務實,但這對我來說太過分了!

static MyClass & myLocalVariable = * new MyClass(/*parameters*/);

真的嗎? 為什么不簡單:

static MyClass myLocalVariable{/*parameters*/};

最明顯的原因是,如果你沒有保留新返回的指針的副本,你就不可能在其上調用delete。

在更人性化的層面上,它會讓人們閱讀你的代碼時更少考慮你,這也不是一件好事。

我相信聲明的用戶意味着使用new分配靜態對象是危險的,因為內存最有可能被泄露。 更重要的是,您的變量不是指針而是引用,因此您永遠不會釋放new返回的內存的可能性更大(您多久刪除一次引用的地址?)。

問題不僅僅是無用的分配。

如果沒有人調用刪除,它將不會被刪除。 當然,程序結束時會釋放內存但是它的析構函數不會被調用。

比較下面代碼中使用Get()Get2()的輸出:

    #include <iostream>

    struct A
    {
        ~A(){std::cout << "Deleted\n";}
    };

    A& Get()
    {
      static A & a = *new A;
      return a;
    }

    A& Get2()
    {
      static A a;
      return a;
    }

    int main()
    {
       //Case 1
       Get();
       //Case 2
       Get2();
    }

在調用Get2時調用GetDeleted時,此程序的輸出Get2
換句話說,在情況1中,在程序終止時不會正確銷毀具有非平凡析構函數(例如,提交關閉文件句柄)的資源,但在情況2中將不會。

問題是raw new不指定所有權。 如果我新建一個物體並將其歸還,誰擁有它? 創建函數/對象是擁有它還是調用函數? 如果返回智能指針(std :: shared_ptr和std :: unique_ptr),則指定所有權。

不指定所有權是泄漏內存的最簡單方法之一。 即使是專業的程序員,我也是最艱難的時刻,讓人們了解所有權並使用它。 這主要是通過使用指定所有權的好類型(智能指針)來防止,只是通過現有的。

type* function();    // Unspecified ownership.
                     // Must be well documented and all users must read
                     // and follow the documentation.
std::unique_ptr<type> function(); // Calling function owns returned pointer.
                                  // Single ownership.
std::shared_ptr<type> function(); // Calling function owns returned pointer.
                                  // Shared ownership.  Can have multiple owners.
std::weak_ptr<type> function();   // Calling function references returned pointer.
                                  // Must lock pointer to get owned object, if not deleted.
                                  // Shared ownership.  Can have multiple owners.

這些不同類型的指針僅通過與原始指針不同的現有表達所有權。

至於new總是錯的。 這是一個過於籠統的概括。 std::shared_ptr是使用全局函數std::make_shared創建的。 從C ++ 11開始,沒有std::make_unique ,但這將在C ++ 14中修復。 創建std::unique_ptr的唯一方法是使用new並立即將指針指定給std::unique_ptr

還有一些地方你需要一個原始指針,並手動使用newdelete ,但它們往往是非常低的水平,大多數程序員很少會遇到它們。


真正讓我對你的代碼感到困惑的不是你使用的是new而是你正在取消引用指針並將它指定給引用。 幾乎不可能保證析構函數將被調用。 它也傾向於泄漏內存,但是在分配給靜態變量的情況下,它將在程序終止時解除分配,因此您不會真正關注內存泄漏。

MyClass& MyClass::MyInstance()
{       
    static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
    return myLocalVariable ;
}

我寧願創建靜態變量是按值而不是通過引用。 這可以防止將對象放在堆上。 根據MyClass還可以允許對象從可執行文件映射到內存,而無需運行任何代碼來初始化它。

MyClass& MyClass::MyInstance()
{
    static MyClass myLocalVariable(/*parameters*/);
    return myLocalVariable ;
}

暫無
暫無

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

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