C++ C++;:具有未知删除器的唯一\u ptr

C++ C++;:具有未知删除器的唯一\u ptr,c++,pointers,memory-management,unique-ptr,C++,Pointers,Memory Management,Unique Ptr,我需要编写一个函数来检索和处理一些数据。此数据可通过多种方式分配(在数据段、堆、共享内存段等上): 由于数据可能是动态分配的,因此我认为处理它的最佳方法是使用唯一的\u ptr或其他类型的智能指针。但是,它并不总是动态分配的:我需要在运行时为unique\u ptr选择deleter,但这是不可能的 我应该如何定义和处理数据?使用您自己的智能指针和您选择的删除器: enum DataPointerType { Stack, Dynamic, SharedMem,

我需要编写一个函数来检索和处理一些数据。此数据可通过多种方式分配(在数据段、堆、共享内存段等上):

由于
数据
可能是动态分配的,因此我认为处理它的最佳方法是使用
唯一的\u ptr
或其他类型的智能指针。但是,它并不总是动态分配的:我需要在运行时为
unique\u ptr
选择deleter,但这是不可能的


我应该如何定义和处理
数据

使用您自己的智能指针和您选择的删除器:

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);
};
枚举数据点类型
{
堆栈
动态
SharedMem,
...
};
模板
类数据指针
{
公众:
数据指针(T*指针,数据指针类型)
:_ptr(指针),_type(类型)
{ }
~DataPointer()
{
开关(类型){
案例堆栈:中断;
大小写动态:delete _ptr;_ptr=nullptr;break;
...
}
}
T&运算符*(){return*ptr;}
常量T&运算符*()常量{return*ptr;}
T*运算符->(){return\u ptr;}
常量T*运算符->()常量{return ptr;}
私人:
T*_ptr;
数据点类型_类型;
//防止复制和破坏,否则会造成危险
数据指针(常量数据指针和其他);
数据指针和运算符=(常量数据指针和其他);
};

我不确定是否使用
std::unique\u ptr
,但您可以使用
std::shared\u ptr
。它的自定义删除器不依赖于类模板参数。

如果使用共享的
共享\u ptr
,则可以在运行时选择删除器。只要你不复制/。。。
shared_ptr
的行为应该与
unique_ptr
的行为相同。您可以使自定义删除程序具有运行时值

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});
struct MyCustomDeleter
{
记忆型;
模板
void运算符()(T*值)常量
{
开关(类型)
{
案例内存类型::堆:
删除[]值;
打破
案例记忆类型::shm:
从\u shm(值)取消映射\u;
打破
//等等。
}
}
};
...
标准::唯一性(新T[尺寸],
MyCustomDeleter{MemoryType::heap});

除了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.
}
typedef std::unique_ptr ptr;
void delete_global(void*);
void delete_heap(void*);
//等等。
Ptr get(/*无论什么*/)
{
如果(…)
返回Ptr(数据,删除\u全局);
如果(…)
返回Ptr(数据,删除堆);
//等等。
}

有趣的相关阅读:。这是一种特殊情况,其中作为类型一部分的删除器类型通过单个函数中断了对不同删除器类型的
unique\u ptr
的使用。。。我的建议是:使用
shared_ptr
在删除器上执行类型擦除…当然,
unique_ptr
的部分价值在于防止您意外复制。这可以工作,但除了在删除器上执行类型擦除的
unique_ptr
版本所需的额外开销之外。维护引用计数时的额外增量和减量可能无关紧要,但这是线程安全的增量和减量。不过,在第一步中使用它比在你意识到它的重要性之前写下你自己的智能指针要好。@bames53:如果它重要的话,我会像肯尼特建议的那样选择一个自定义的删除器,可能有点修改成一个函子。我用了一个类似于你建议的解决方案来解决我的问题。不管怎样,我的代码看起来真的很难看。。。我正在考虑在接下来的几天里提出一个新的问题,关于如何真正实现这一点。谢谢!:)
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.
}