c++ - 在 C++20 中,我们可以将标头和数据对象打包在一起,并通过偏移量从标头访问数据吗?
问题描述
struct header
{
int a1;
int a2;
// ...;
std::byte * get_data_bytes()
{
return align_up<data>( // make sure alignment requirements are met
reinterpret_cast<std::byte *>(this) + sizeof(*this));
// maybe std::launder around the reinterpret_cast (only) is needed?
}
data & get_data()
{
return *std::launder(reinterpret_cast<data *>(get_data_bytes()));
}
void use_data()
{
get_data().use();
}
};
void example()
{
alignas(header) std::byte storage[/* plenty of space*/];
auto h = new (storage) header;
new (h->get_data_bytes()) data;
h->use_data(); // Does this eventually cause a UB?
}
没有UB这可能吗?如果没有,是否有替代方案?要求是数据不是标头的子对象,并且标头中没有指向数据的指针/引用以避免额外的间接性。这可能通过灵活的空数组实现,但我认为这些不在标准中。
解决方案
唯一甚至假设是 UB 是是否reinterpret_cast<std::byte *>(this)
是指向数组中字节之一的指针。但是你可以std::launder
确保它是。事实上,对字节指针进行清洗非常有用,您可以为它们创建模板函数:
template<typename T>
std::byte *to_byte_ptr(T *ptr)
{
return std::launder(reinterpret_cast<std::byte*>(ptr));
}
template<typename T>
T *from_byte_ptr(std::byte *ptr)
{
return std::launder(reinterpret_cast<T*>(ptr));
}
其他一切都很好。您header
在由字节数组提供的存储中创建,因此std::byte
可以通过launder
. 而且由于这些std::byte
对象位于数组中,因此您可以对它们进行指针运算。虽然这些std::byte
对象实际上并不指向它们为其提供存储的对象,但如果您有一个与所需对象具有相同地址的指针,您可以launder
检索指向该对象的指针。
推荐阅读
- reactjs - 单元测试:动作必须是普通对象。使用自定义中间件进行异步操作
- python - 使用 Windows 10 在 python 中输入 PS4 控制器
- postgresql - 如何使用环回 4 进行修复(将 rest 转换为 graphql):OPTIONS http://localhost:3001/graphql 405(不允许的方法)
- django - django.db.utils.ProgrammingError:运算符不存在:字符变化> =整数
- xml - 在 Flutter 中显示来自 XML 的动态列表视图
- nlp - StanfordNLP、CoreNLP、spaCy - 不同的依赖图
- python - 为什么这段代码不会呈现我输入的问题和答案?
- android - 如何发布列表
在android上进行多部分改造? - laravel - SQLSTATE [23000]:完整性约束违规:1452 无法添加或更新子行 [0 下拉值]
- javascript - NodeJS如何循环查询