2012-03-02 133 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. 
} 
相关问题