我知道这是一个相当普遍的主题,但尽管通常的UB很容易找到,但我到目前为止没有找到这个变体。
所以,我正在尝试在避免实际复制数据的情况下正式引入像素对象。
这是有效的吗?
预期使用模式,大大简化:
更具体地说:
所以,我正在尝试在避免实际复制数据的情况下正式引入像素对象。
这是有效的吗?
struct Pixel {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
};
static_assert(std::is_trivial_v<Pixel>);
Pixel* promote(std::byte* data, std::size_t count)
{
Pixel * const result = reinterpret_cast<Pixel*>(data);
while (count-- > 0) {
new (data) Pixel{
std::to_integer<uint8_t>(data[0]),
std::to_integer<uint8_t>(data[1]),
std::to_integer<uint8_t>(data[2]),
std::to_integer<uint8_t>(data[3])
};
data += sizeof(Pixel);
}
return result; // throw in a std::launder? I believe it is not mandatory here.
}
预期使用模式,大大简化:
std::byte * buffer = getSomeImageData();
auto pixels = promote(buffer, 800*600);
// manipulate pixel data
更具体地说:
- 这段代码是否有明确定义的行为?
- 如果是,使用返回的指针是否安全?
- 如果是,可以将其扩展到哪些其他
Pixel
类型?(放宽is_trivial限制?仅具有3个组件的像素?)
无论是clang还是gcc都会将整个循环优化为空,这正是我想要的。现在,我想知道这是否违反了某些C ++规则。
Godbolt链接,如果您想尝试一下。
(注:尽管使用了std::byte
,但我没有标记为 c++17,因为问题可以使用 char
解决。)
pixels
(P)不是指向数组对象的指针,而是指向单个Pixel
的指针。这意味着您只能合法地访问pixels [0]
。 - NathanOliver