【Cxx 20】使用 std::span 代替数组指针传参
我们知道std::string_view
可以创建std::string
的一个视图,视图本身并不拥有实例,它只是保持视图映射的状态。在不修改实例的情况下,使用std::string_view
会让字符串处理的性能大幅提升。实际上,对于那些连续的序列对象我们都可以创建这样一份视图,对于std::vector
这样的对象可以提高某些操作中的性能,另外对原生数组可以提高其访问的安全性。
过去如果一个函数想接受无法确定数组长度的数组作为参数,那么一定需要声明两个参数:数组指针和长度:
void set_data(int *arr, int len) {}
int main()
{
int buf[128]{ 0 };
set_data(buf, 128);
}
这种人工输入增加了编码的风险,数组长度的错误输入会引发程序的未定义行为,甚至是成为可被利用的漏洞。C++20标准库为我们提供了一个很好解决方案std::span
,通过它可以定义一个基于连续序列对象的视图,包括原生数组,并且保留连续序列对象的大小。例如:
#include <iostream>
#include <span> // CXX 20
void set_data(std::span<int> arr) {
std::cout << arr.size();
}
int main()
{
int buf[128]{ 0 };
set_data(buf);
}
除了原生数组,std::vector
和std::array
也在std::span
的处理之列:
std::vector<int> buf1{ 1,2,3 };
std::array<int, 3> buf2{ 1, 2, 3 };
set_data(buf1);
set_data(buf2);
值得注意的是,std::span
还可以通过构造函数设置连续序列对象的长度:
int buf[128] = {0};
set_data({buf, 16});
从std::string_view
到std::span
,我们可以看出C++标准库很乐于这种视图设计,因为这种设计和抽象的实现可以提高C ++程序的可靠性而又不牺牲性能和可移植性。