如何在转换为 void* 并返回后删除指针

How to delete a pointer after cast to void* and back

作为 "message"-class 的一部分,我尝试通过将不同类型的指针转​​换为 void* 指针并将它们保存在包装器 class 中来传输不同类型的指针("MsgData") 记住指针的原始类型。

例如布尔指针:

bool* data = new bool;
event.wheel.y < 0 ? *data = false : *data = true;
send("all", this, MSG_MOUSE_SCROLL, MsgData(data));

调用了MsgData的兼容构造函数并将变量保存为我的消息的成员class:

MsgData():                        type_(NULLPTR),    data_(nullptr)     {}  // Null
MsgData(const bool* data):        type_(BOOL),       data_((void*)data) {}  // Bool
MsgData(const std::string* data): type_(STRING_STD), data_((void*)data) {}  // std::string
// ... etc.

我可以将指针转换回去并使用它们而不会出现任何错误,但是当我尝试删除它们时程序崩溃了:

~MsgData() {
    switch (type_) {
    case (BOOL):
        if ((bool*)data_)
            delete (bool*)data_;
        break;
    // ... etc.
    }
}

bool 指针只是一个例子,所有其他类型和 classes 也是如此。 只有当我尝试删除指针时,程序才会崩溃。将它们转换回原始类型并使用它们不是问题。

我研究了这个问题并在 Whosebug 上发现了类似 this one 的问题,但是虽然将指针投射到 void* 并返回似乎被认为是不好的风格,但我找不到程序崩溃的原因。

嗯,更好的解决问题的方法是使用boost::variant(或std::variant)。一旦你开始使用它,删除和管理 typedata 的所有麻烦都会自动消失。您不是第一个遇到此类问题的人;许多其他人都遇到过它,解决方案以 boost::variantstd::variant.

的形式提供

无论如何,由于您正在自己开发解决方案,因此我的建议是:在构造函数本身中构造一个适当的 deleter .. 或者只要您知道 type of data 你的 class 将持有:

MsgData()
 : type_(NULLPTR), data_(nullptr)     {} 

MsgData(const bool* data)
 : type_(BOOL), data_((void*)data), deleter_(&deleter<BOOL>) {}      

MsgData(const std::string* data)
 : type_(STRING_STD), data_((void*)data), deleter_(&deleter<std::string>) {}  

其中 deleter_ 是成员:

std::function<void(void const*)>  deleter_;

deleter被定义为函数模板:

template<typename T>
void deleter(void const * data) {
   delete static_cast<T const *>(data);
}

一旦有了这些,您的析构函数将如下所示:

~MsgData() {
   if (deleter_) {
      deleter_(data_);
   }
}

希望对您有所帮助。