当使用具有可变大小结构的各种API(必须分配为byte []然后转换为结构的结构)时,如果unique_ptr持有者可以指向结构,那将是很好的,因为#39; s我们将要使用的东西。
示例:
std::unique_ptr<VARIABLE_SIZE_STRUCT[]> v;
v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(new BYTE[bytesRequired]));
这允许`v为结构本身提供视图,这是优选的,因为我们不需要第二个变量,除了删除之外我们不关心字节指针。
问题在于可能会在演员表上敲击指针(使其免于安全)。我认为没有合理的理由为什么编译器会改变转换时的指针值(因为没有继承),但是我听说标准保留了在任何转换中使用任何指针的权利,所以标准兼容编码去了,这种方法是窗外的吧?或者有什么理由它是安全的吗?有没有办法至少static_assert这个,或其他一些方法来使它安全或干净地处理这种类型的结构?
答案 0 :(得分:5)
你是对的,这是不安全的。但是,它可以使它安全。
该标准保证如果您reinterpret_cast
为其他类型,然后返回原始类型,则会返回原始值。
您可以将它与自定义删除器一起使用,以确保将内部指针强制转换为释放它之前分配的类型。
auto deleter = [](VARIABLE_SIZE_STRUCT* ptr)
{
delete[] reinterpret_cast<uint8_t*>(ptr);
};
std::unique_ptr<VARIABLE_SIZE_STRUCT, decltype(deleter)> v
(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(new uint8_t[256]), deleter);
此时,您可能最好不要创建自己的包装而不使用unique_ptr
。
答案 1 :(得分:5)
您的分配可能没有VARIABLE_SIZE_STRUCT
分配的内存中没有VARIABLE_SIZE_STRUCT位置的对象 - new
在其中 - 假设您处理它,unique_ptr
的默认析构函数逻辑应该找到要销毁的预期对象实例,但是释放本身不会在delete []
上使用BYTE*
完成 - 要定义行为,您必须自定义删除器才能首先调用{{1然后~VARIABLE_SIZE_STRUCT()
...
如果您关注&#34; thunking&#34;,您可以在运行时进行检查:
delete[]
背景 - 5.2.10 / 7:
可以将对象指针显式转换为不同类型的对象指针。当对象指针类型的prvalue v转换为对象指针类型“指向cv T的指针”时,结果为
BYTE* p; v.reset(reinterpret_cast<VARIABLE_SIZE_STRUCT*>(p = new BYTE[bytesRequired])); assert(reinterpret_cast<BYTE*>(v.get()) == p);
。将“指向T1的指针”的prvalue转换为“指向T2的指针”类型(其中T1和T2是对象类型,T2的对齐要求不比 那些T1)并返回其原始类型产生原始指针值。
因此,如果static_cast<cvT*>(static_cast<cv void*>(v))
的对齐要求比VARIABLE_SIZE_STRUCT
更严格,则您保证不会使用BYTE
检索原始指针