C++中的std::string_view和std::span

string_view是C++17标准引入,std::span是C++20引入,两个特性都比较类似。
(1)std::string_view
string_view是字符串的视图,由于传统的string存在以下问题:
字符串字面值、字符数组、字符串指针的传递仍要数据拷贝:字符串指针和字符数组某些情况下可能会比较大(比如读取文件的内容),此时会引起频繁的内存分配和数据拷贝,会严重影响程序的性能。
substr O(n)复杂度:每次都返回一个新生成的子串
效率较低,内存开辟在堆上。
因此引入了string_view来解决以上问题,Std::string_view只是获取字符串视图,并不真正创建或者拷贝字符串,只是拥有一个字符串查看功能
,不可写。它的原型是using std::string_view = std::basic_string_view
string_view仅保存指向数据起始指针和长度,开销较小。
构造函数:

constexpr string_view() noexcept;
constexpr string_view(const string_view& other) noexcept = default;
constexpr string_view(const CharT* s, size_type count);
constexpr string_view(const CharT* s);
string_view foo(string("abc"))

因为string类重载了string到string_view的转换操作符,所以也支持:string_view foo(string(“abc”));
自定义字面量:
比如\0对于字符串而言,有其特殊的意义,即表示字符串的结束,字符串视图,它关心实际的字符个数,所以可以自定义字面量。
成员函数:
跟string的只读函数基本一致,string_view的substr函数的时间复杂度是O(1),swap函数仅会修改string_view的数据指向,不会修改指向的数据。
使用注意事项:
1.string_view范围内的字符可能不包含\0,而cout输出需要以\0结尾的函数使用时可能会越界。
2.从[const] char*构造string_view对象时间复杂度O(n)
3.string_view指向的内容的生命周期可能比其本身短

string_view foo() {
    std::string s{"hello world"};
    return string_view{s};
}

(2)std::span
span 是一个轻量级的非拥有式容器,它提供了对连续内存的引用。 span 的主要用途是作为函数参数,可以避免不必要的内存拷贝,并且可以防止悬垂指针和空指针引用的问题。span和string_view非常类似,与是用于描述一段连续的内存序列,最大的作用是可以用于代替数组作为函数参数,如果把数组作参数时(非引用)会退化为指针,还得传递数组的长度。span,即可以用于读,也可以用于修改元素值(但不能增删元素),且代码更简单,更安全,不会越界。
span使用场景:
1.作为函数的参数,用于指示函数需要处理的数据范围;
2.作为类的成员变量,用于表示对象所管理的内存区域;
3.作为数组的视图,用于访问数组的一部分
使用方法:

数组转换为 span:
int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);
遍历容器:
vector<int> vec = {1, 2, 3, 4, 5};
for (auto&& x : span(vec)) {
    cout << x << " ";
}
使用 span 来获取子序列:
int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);
auto s1 = s.subspan(1, 3);
将 span 转换为其他容器类型:
int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);
vector<int> vec(s.begin(), s.end());

span 与 array ,vector的区别
span 是 C++20 中新增的一个轻量级容器,用于表示一段连续的内存区域,它不负责管理内存空间,也不会拥有所指向内存的所有权,只是提供一种方便的方式来操作内存区域,因此可以看做是一个只读的“裸指针”。

与 array 和 vector 相比,span 的主要区别在于它不拥有自己的存储空间,而是引用了另一个数组或容器的内存空间。因此,当我们需要使用一个连续的内存块时,可以使用 span 来代替 array 或 vector。

具体来说,array 是一个固定大小的数组容器,其大小在编译时就确定了,不能动态改变。vector 是一个动态增长的数组容器,可以动态分配内存,并在需要时扩大容量。而 span 是一个非拥有型的容器,可以看作是一个指向连续内存区域的引用,可以指向任何类型的元素。

在使用方面,array 和 vector 可以用来存储数据,并通过下标或迭代器来访问其中的元素;span 则更多地用来表示一段内存区域,并提供类似于迭代器的操作来访问其中的元素(就是 只读),如 begin、end、rbegin、rend 等。
参考:
https://blog.csdn.net/danshiming/article/details/122653625
https://zhuanlan.zhihu.com/p/589182023
https://blog.csdn.net/Appleeatingboy/article/details/129314624

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值