2012-03-02 67 views
2

我需要編寫一個函數來檢索和處理一些數據。該數據可以用幾種方式來分配(在數據段,在堆上,在一個共享內存段等):C++:unique_ptr with unknow deleter

T *data; 
if(global) data = &d; 
if(heap) data = new T [ size ]; 
if(shm) data = (T*) shmat(id, 0, 0); 
// processing data ... 

由於data可以動態地分配,我倒是覺得,最好的辦法處理它是使用unique_ptr或其他類型的智能指針。但它並不總是動態分配的:我需要在運行時選擇unique_ptr的刪除程序,但這不可能。

我該如何定義和處理data

+3

有趣的相關閱讀:[走向更美好的分配器模型(http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cts=1330701318745&ved=0CCYQFjAA&url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22 %2Fwg21%2Fdocs%2Fpapers%2F2005%2Fn1850.pdf&EI = A-RQT-DXBeXA0QGJqqXFDQ&USG = AFQjCNFS07GH0af749GIyOIjE-QCC-K7dw&SIG2 = hBWQcfg-EUOmH2d8UI5UuQ)。這是一種特殊情況,刪除程序的類型屬於類型的一部分,通過一個函數破壞了具有不同刪除程序類型的'unique_ptr'的使用...我的推薦:在刪除程序中執行類型刪除時使用'shared_ptr'。 .. – 2012-03-02 15:18:33

回答

6

您可以讓自定義刪除器獲得運行時間值!

struct MyCustomDeleter 
{ 
    MemoryType type; 
    template <typename T> 
    void operator()(T* value) const 
    { 
     switch (type) 
     { 
     case MemoryType::heap: 
      delete[] value; 
      break; 
     case MemoryType::shm: 
      unmap_from_shm(value); 
      break; 
     // etc. 
     } 
    } 
}; 

... 

std::unique_ptr<T, MyCustomDeleter> ptr (new T[size], 
             MyCustomDeleter{MemoryType::heap}); 
+0

我使用了一種類似於您提議解決問題的解決方案。無論如何,我的代碼看起來非常醜陋......我想在接下來的幾天中提出一個新的問題,關於如何實際實現這一點。謝謝! :) – peoro 2012-03-04 21:17:24

1

使用自己的智能指針與你選擇一個缺失者:

enum DataPointerType 
{ 
    Stack, 
    Dynamic, 
    SharedMem, 
    ... 
}; 

template <class T> 
class DataPointer 
{ 
public: 
    DataPointer(T* pointer, DataPointerType type) 
     : _ptr(pointer), _type(type) 
    { } 

    ~DataPointer() 
    { 
     switch (type) { 
     case Stack: break; 
     case Dynamic: delete _ptr; _ptr = nullptr; break; 
     ... 
     } 
    } 

    T& operator*() { return *_ptr; } 
    const T& operator*() const { return *ptr; } 

    T* operator->() { return _ptr; } 
    const T* operator->() const { return ptr; } 

private: 
    T* _ptr; 
    DataPointerType _type; 

    // Prevent copying and destruction, dangerous 
    DataPointer(const DataPointer& other); 
    DataPointer& operator=(const DataPointer& other); 
}; 
3

我不知道std::unique_ptr,但你可以使用std::shared_ptr。其定製刪除器不依賴於類模板參數。

+2

這可以工作,但是額外的開銷遠遠超過了刪除程序類型擦除的'unique_ptr'版本所需的額外開銷。維護引用計數的額外增量和減量可能無關緊要,但它是線程安全的增量和減量。儘管如此,在第一遍使用它之前,最好先寫好自己的智能指針,然後才能知道它的重要性。 – bames53 2012-03-02 15:43:04

+0

@ bames53:在這種情況下,我會選擇一個自定義的刪除程序,正如KennyTM所提出的,可能需要修改才能使用函子。 – 2012-03-02 15:46:57

1

如果使用共享shared_ptr<>,則可以在運行時選擇刪除程序。只要你不復制/ ... shared_ptr它應該表現得像unique_ptr一樣。

+0

當然,'unique_ptr'的一部分價值在於它可以防止你意外複製。 – bames53 2012-03-02 15:36:21

3

除了KennyTm的很好的答案,另一種可能是使用函數指針爲您刪除器,然後在運行時提供不同的功能:

typedef std::unique_ptr<T, void(*)(void*)> Ptr; 
void delete_global(void*); 
void delete_heap(void*); 
// etc. 

Ptr get(/* whatever */) 
{ 
    if (...) 
     return Ptr(data, delete_global); 
    if (...) 
     return Ptr(data, delete_heap); 

    // etc. 
}