因此gcc 4.9.0
implemented static_assert
个void
离子类型不是std::unique_ptr<void>
才能正确符合标准。这很棒,一切都符合标准。
我有一种变体类型,它将数据存储在std::shared_ptr<void>
下,现在无效。简单的解决方法是将其更改为unique_ptr
并立即编译。更好的解决方法是提供删除函数。
以下是修复#include <memory>
#include <iostream>
template<typename T>
void Deleter(void * p) {
delete reinterpret_cast<T*>(p);
}
int main() {
const std::unique_ptr<void, void(*)(void*)> v(new int(199), Deleter<int>);
std::cout << *reinterpret_cast<int*>(v.get()) << std::endl;
return 0;
}
的安全方法吗?这会出现某些多态类型的未定义行为吗?
{{1}}
答案 0 :(得分:9)
这会出现某些多态类型的未定义行为吗?
如果您使用unique_ptr<void, void(*)(void*)>(new X(...), Deleter<X>)
对任何X
都是正确的,因为删除器使用对象的正确动态类型。
如果您使用unique_ptr<void, void(*)(void*)>(new Derived(...), Deleter<Base>)
将会有未定义的行为(对于多态和非多态类型),如果Base
没有虚拟析构函数,或者Base
子对象与包含它的Derived
对象的地址不同。
但是,您应该在两个地方使用static_cast
而不是reinterpret_cast
。您应该更喜欢使用最适合特定情况的强制转换,reinterpret_cast
是一个大锤。
为了使代码不易出错,我会写一个辅助函数,所以你只需要输入一次类型,如:
template<typename T, typename... Args>
std::unique_ptr<void, void(*)(void*)>
make_unique_void_ptr(Args&&... args)
{
using Ptr = std::unique_ptr<void, void(*)(void*)>;
return Ptr{ new T(std::forward<Args>(args)...), Deleter<T> };
}