如何在转换为 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
)。一旦你开始使用它,删除和管理 type 和 data 的所有麻烦都会自动消失。您不是第一个遇到此类问题的人;许多其他人都遇到过它,解决方案以 boost::variant
或 std::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_);
}
}
希望对您有所帮助。
作为 "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
)。一旦你开始使用它,删除和管理 type 和 data 的所有麻烦都会自动消失。您不是第一个遇到此类问题的人;许多其他人都遇到过它,解决方案以 boost::variant
或 std::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_);
}
}
希望对您有所帮助。