簡體   English   中英

刪除靜態向量中的唯一類對象指針

[英]Deletion of unique class object pointers in a static vector

假設我們創建一個名為Window的簡單類,並希望使用std::unique_ptr的向量跟蹤我們擁有的所有窗口:

#include <vector>
#include <memory>

class Window {
public:
    static std::vector<std::unique_ptr<Window>> MemberPointers;
private:
    int width;
    int height;

};

我們在這個類的構造函數中為創建的對象分配指針。

根據Bjarne Stroustrup的“A Tour of C ++”, std::unique_ptr在超出范圍時會被釋放,就像常規的局部變量一樣。 這是否意味着,在這個類的解構函數中,我不需要調用任何東西來delete指向該對象的vector元素?

如果沒有,我怎么能用std::erasestd::remove_if刪除正確的對象?

你誤解了unique_ptr的目的。 它假定它擁有指針的對象由new分配,並在其析構函數中delete該對象。 例:

void f() {
    std::unique_ptr<int> ptr{new int(123)};
} //the int allocated by new is deleted here by ptr's dtor

假設你實現了這樣的類:

class Window {
public:
    Window(int w, int h) :width{w}, height{h}
    {
        MemberPointers.emplace_back(this);
    }
    static std::vector<std::unique_ptr<Window>> MemberPointers;
private:
    int width;
    int height;
};

然后,在main ,你這樣做:

Window win{1000, 500};

現在Window::MemberPointers包含一個元素: unique_ptr holding &win

最后,當整個程序完成時,會話成員的MemberPointers被調用。 unique_ptr嘗試delete win 請注意, win不是由new分配的,因此會導致未定義的行為。

摘要:
你的目的是在指針被破壞時從MemberPointers中刪除指針本身 ,但事實是它試圖delete指針對象, 使指針本身仍然在MemberPointers中。

正確的設計很簡單:沒有unique_ptr

class Window {
public:
    Window(int w, int h) :width{w}, height{h}
    {
        MemberPointers.emplace_back(this);
    }
    ~Window()
    {
        auto p = std::remove(MemberPointers.begin(), MemberPointers.end(), this);
        MemberPointers.erase(p, MemberPointers.end());
    } // remove this from MemberPointers
    static std::vector<Window*> MemberPointers;
private:
    int width;
    int height;
};

或者,使用std::set更好更高效:

class Window {
public:
    Window(int w, int h) :width{w}, height{h}
    {
        MemberPointers.emplace(this);
    }
    ~Window()
    {
        MemberPointers.erase(this);
    } // remove this from MemberPointers
    static std::set<Window*> MemberPointers;
private:
    int width;
    int height;
};

使用std::vector的設計具有復雜度O( n ),其中n是對象的數量; 使用std::set的設計具有復雜度O(log( n ))(如果您實際創建了大量對象,則效率會大大提高)。

是的, std::erasestd::remove_if ,以及從std::vector (包括析構函數)中刪除元素的任何其他函數,調用它們刪除的每個元素的析構函數。

調用unique_ptr的析構函數會破壞它指向的對象。 這可以通過超出范圍(如果它在堆棧中)或顯式刪除指向它的指針(如果它在堆中)來實現。

在這種情況下, MemberPointers向量將在程序終止之前銷毀,它將調用其元素的析構函數(在堆上分配unique_ptr ),因此不會泄漏任何內存。

暫無
暫無

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

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