将指针算术替换为std::span

  • 本文关键字:std span 替换 指针 c++
  • 更新时间 :
  • 英文 :


我有以下使用指针算术的代码,并希望使用std::span(或者,我想是gsl::span(替换它。该代码在多个像素上迭代,每个像素由4个连续字节表示,并更新它们的蓝色和绿色。

auto* row = (uint8_t*)buffer->data;
for (auto y = 0; y < buffer->height; ++y) {
auto* pixel = (uint32_t*)row;
for (auto x = 0; x < buffer->width; ++x) {
auto blue = x + blueOffset;
auto green = y + greenOffset;
*pixel++ = ((green << 8) | blue);
}
row += buffer->pitch;
}

buffer->data是从对WindowsVirtualAlloc(...)函数的调用返回的void*

如何按照C++核心指南和Moderns C++的建议,编写此代码以使用安全、现代的C++,如std::span

这与C++20、gsl和gsl-lite中的每一个一起编译。由于您没有提供可复制的示例,我没有测试或基准测试此解决方案。

auto const my_span = span{
reinterpret_cast<uint8_t *>(buffer->data),
buffer->height * buffer->pitch};
constexpr auto size_ratio = sizeof(uint32_t) / sizeof(uint8_t); // 4
auto const uint8_width = size_ratio * buffer->width;
auto row_offset = 0UL;
auto row = my_span.subspan(row_offset, buffer->width);
for (auto y = 0; y < buffer->height; ++y) {
auto const pixels = span{
reinterpret_cast<uint32_t *>(row.data()),
buffer->width};
auto pixel = pixels.begin();
for (auto x = 0; x < buffer->width; ++x) {
auto const blue = x + blueOffset;
auto const green = y + greenOffset;
*pixel++ = ((green << 8) | blue);
}
row_offset += buffer->pitch;
row = my_span.subspan(row_offset, uint8_width);
}

显然,由于将相同的内存解释为uint8_tuint32_t,因此在这里使用跨度并不一定会使代码更容易读取。跨度仍然应该提供更多的安全性。

通过在buffer所指向的结构中提供更多的成员或成员函数,可以使代码更容易阅读。例如,成员函数可以为您提供所需的子扫描,或者至少提供uint8_width。由于没有人问我,我没有碰这里的结构。它可能是由库提供的,但在这种情况下仍然可以编写包装器。

最新更新