更多 C++ 習語/具體資料型別
外觀
透過允許或禁止使用自由儲存(堆)進行動態分配來控制物件的範圍和生命週期
本節內容為空。請透過 擴充套件它 來幫助我們。 |
C++ 提供了兩種方法來控制物件的生存期並將其繫結到程式級識別符號(變數)。第一種是作用域變數和物件,它們在作用域結束後立即被銷燬(例如,函式作用域中的整數)。第二種是作用域變數(通常是指標)和自由儲存中動態分配的物件。在這種情況下,在變數作用域結束時,變數將不再存在,但物件的生存期將繼續(例如,單例、視窗物件)。可以使用具體資料型別習語強制選擇物件生存期的第一種方式或第二種方式。
此習語簡單地使用類級訪問修飾符(private、protected)來實現目標。以下程式碼展示了 MouseEventHandler 類如何強制動態分配。
class EventHandler
{
public:
virtual ~EventHandler () {}
};
class MouseEventHandler : public EventHandler // Note inheritance
{
protected:
~MouseEventHandler () {} // A protected virtual destructor.
public:
MouseEventHandler () {} // Public Constructor.
};
int main (void)
{
MouseEventHandler m; // A scoped variable is not allowed as destructor is protected.
EventHandler *e = new MouseEventHandler (); // Dynamic allocation is allowed
delete e; // Polymorphic delete. Does not leak memory.
}
強制動態分配的另一種方法是阻止對建構函式的直接訪問,而是提供一個靜態函式 instance() 來返回一個動態分配的物件。它在許多方面類似於單例設計模式。此外,嚴格來說,使用多型刪除來回收記憶體並不是必需的。一個成員函式 destroy() 可以達到這個目的,從而節省了用於 v-table 指標的空間。
class MouseEventHandler // Note no inheritance
{
protected:
MouseEventHandler () {} // Protected Constructor.
~MouseEventHandler () {} // A protected, non-virtual destructor.
public:
static MouseEventHandler * instance () { return new MouseEventHandler(); }
void destroy () { delete this; } // Reclaim memory.
};
此習語的另一個極端是強制使用作用域變數(又稱自動變數)。這可以透過使用私有 new 運算子來實現。
class ScopedLock
{
private:
static void * operator new (size_t size); // Disallow dynamic allocation
static void * operator new (size_t, void * mem); // Disallow placement new as well.
};
int main (void)
{
ScopedLock s; // Allowed
ScopedLock * sl = new ScopedLock (); // Standard new and nothrow new are not allowed.
void * buf = ::operator new (sizeof (ScopedLock));
ScopedLock * s2 = new(buf) ScopedLock; // Placement new is also not allowed
}
ScopedLock 物件不能使用 new 運算子、nothrow new 運算子和 placement new 運算子進行動態分配。
- 具體資料型別 - J. Coplien。