2010-12-08 47 views
3

我有一個類A。我正在使用的一些庫爲我分配了一定量的內存,sizeof A,並返回一個void指針。C++:在分配的內存中存儲類實例

A* pObj = (A*) some_allocator_im_forced_to_use(sizeof A); 

現在我怎麼可以創建A一個新的實例,在剛剛分配的內存?

我有嘗試過:

*pObj = A(); 

但這並沒有工作 - 析構函數得到了A的構​​造

回答

8

您可以使用新的位置後立即叫:

A* pObj = new (some_allocator_im_forced_to_use(sizeof(A))) A; 

這會在函數some_allocator_im_forced_to_use返回的位置構造一個新的A實例。這個函數需要返回一個void*,指向足夠的內存,這個內存在正在討論的實現中的A對象上適當對齊。

您很可能必須手動手動調用此對象的析構函數,因爲您將無法使用通常的delete pObj來銷燬它。

pObj->~A(); 
// Call custom allocator's corresponding deallocation function on (void*)pObj 

爲了正確銷燬對象,釋放你可以考慮使用一個shared_ptr與定製刪除的記憶。

3

使用放置新:

new (pObj) A; 

您還需要以不同的方式銷燬對象,因爲delete假設(錯誤地),你用普通的舊new創建的對象:

pObj->~A(); 
some_deallocator_im_forced_to_use(pObj); 
0

如果您分配如下std::allocator模型應當有幾種方法:

  • allocate
  • construct
  • destroy
  • deallocate

他們是非常不言自明的,最重要的是,你有責任美其名曰:

  • 按照正確的順序
  • ,不要忘了任何

或者你會得到UB或泄漏。但是我有點驚訝,只有大小是你的分配器所需要的,通常它還需要對象的對齊,除非是簡單地使用目標上可能的最大對齊方式,而不管對象是否被分配。

1

有些人主張新安置。

這很危險,迄今爲止的兩個使用示例已經省略了關鍵細節,如包含<new>標題,限定呼叫::new ...以及如何清理。

安全的解決方案是爲您的類或派生自類的類定義自定義分配和釋放函數。下面的例子顯示了後者。請注意,虛擬析構函數僅用於支持類派生;如果你不派生,你不需要它。

#include <stddef.h> 
#include <iostream> 

void* some_allocator_im_forced_to_use(size_t size) 
{ 
    std::cout << "Allocated " << size << " bytes." << std::endl; 
    return ::operator new(size); 
} 

void some_deallocator_im_forced_to_use(void* p, size_t size) 
{ 
    std::cout << "Deallocated " << size << " bytes." << std::endl; 
    ::operator delete(p); 
} 

struct A 
{ 
    int x_; 
    A(): x_(42) {} 
    virtual ~A() {} 
}; 

struct CustomAllocedA 
    : A 
{ 
    void* operator new(size_t size) 
    { 
     return some_allocator_im_forced_to_use(size); 
    } 

    void operator delete(void* p, size_t size) 
    { 
     some_deallocator_im_forced_to_use(p, size); 
    } 
}; 

int main() 
{ 
    A* const p = new CustomAllocedA; 

    std::cout << p->x_ << std::endl; 
    delete p; 
} 

重要提示:雖然這本身就是「安全」,儘管這個特殊的例子是安全的,代碼的安全最終取決於您的自定義分配器返回一個指針,以正確對齊的內存。

乾杯&心連心,

+0

+1覆蓋新的運營商是絕對比使用放置新的更好的主意。 – 2010-12-08 16:03:15