[英]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::erase
和std::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::erase
, std::remove_if
,以及從std::vector
(包括析構函數)中刪除元素的任何其他函數,調用它們刪除的每個元素的析構函數。
調用unique_ptr
的析構函數會破壞它指向的對象。 這可以通過超出范圍(如果它在堆棧中)或顯式刪除指向它的指針(如果它在堆中)來實現。
在這種情況下, MemberPointers
向量將在程序終止之前銷毀,它將調用其元素的析構函數(在堆上分配unique_ptr
),因此不會泄漏任何內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.