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