固定大小缓冲区的子范围c++避免原始指针

问题描述 投票:0回答:1

我正在编写一些状态机代码,不同的类负责不同类型的任务,所有这些任务都在获取数据。完成数据采集后,需要将数据发送出去。负责的班级看起来像这样:

class SendBuffer {
    std::uint8_t* get_position(/*some arguments to determine buffer*/) {  
        return &buffer[/*at determined location*/];
    }
private:
    std::array<std::uint8_t, MAX_SIZE> buffer;
};

当然,这根本不安全,因为返回的指针没有缓冲区中专用切片的长度等信息

我考虑返回

std::span<std::uint8_t>
而不是原始指针,但我想知道这里的最佳实践是什么。

c++ buffer raw-pointer
1个回答
0
投票

使用

std::span
(cppreference) 是正确的方法。正如评论中提到的,它可以从视图初始化。另外,
span
的成员函数提供了有用的实用程序。如果出现问题,可以使用
subspan(offset, extent)
函数将单个值作为范围返回。

std::span get_position(std::size_t i) {  
    return std::span(buffer).subspan(i, 1);
}

对于单个值,返回引用可能更有用。但对于缓冲区的子范围,

span
subspan
first
last
很方便。一些例子:

std::array<T, N> buffer;
std::span buffer_view{buffer};    // of type std::span<T, N>
buffer_view.subspan(a)            // range from indices [a, end)
buffer_view.subspan(a, b)         // range from indices [a, a+b)
buffer_view.subspan(a).first<B>() // range from indices [a, a+B) with compile time B
                                  // thus returns std::span<T, B>

请注意

subspan
first
last
具有静态和动态重载

buffer_view.subspan<A, B>() // std::span<T, B>
buffer_view.subspan(a, b)   // std::span<T, std::dynamic_extent>
buffer_view.first<C>()      // std::span<T, C>
buffer_view.first(c)        // std::span<T, std::dynamic_extent>
buffer_view.last<D>()       // std::span<T, D>
buffer_view.last(d)         // std::span<T, std::dynamic_extent>

其中大写字母表示编译时间常数,小写字母也可以表示运行时大小。

© www.soinside.com 2019 - 2024. All rights reserved.