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

文章介绍了C++17引入的string_view和C++20引入的std::span特性。string_view作为字符串的视图,解决了传统string的拷贝和性能问题,提供了一种轻量级的只读方式来处理字符串。std::span则是一个非拥有式的容器,用于表示连续内存区域,常用于函数参数和内存安全的访问,提高了代码效率和安全性。两者都是为了减少内存拷贝和提高程序性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

当__cplusplus == 202400 为啥cmd /c chcp 65001>nul && D:\mingw_msys2\ucrt64\bin\g++.exe -fdiagnostics-color=always -g D:\bicheng\zhzy\hello.cpp -o D:\bicheng\zhzy\hello.exe -std=c++26 -O2 D:/mingw_msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\李逸扬\AppData\Local\Temp\ccQ0Og5z.o: in function `std::vprint_unicode(_iobuf*, std::basic_string_view<char, std::char_traits<char> >, std::basic_format_args<std::basic_format_context<std::__format::_Sink_iter<char>, char> >)': D:/mingw_msys2/ucrt64/include/c++/15.1.0/print:81:(.text$_ZSt14vprint_unicodeP6_iobufSt17basic_string_viewIcSt11char_traitsIcEESt17basic_format_argsISt20basic_format_contextINSt8__format10_Sink_iterIcEEcEE[_ZSt14vprint_unicodeP6_iobufSt17basic_string_viewIcSt11char_traitsIcEESt17basic_format_argsISt20basic_format_contextINSt8__format10_Sink_iterIcEEcEE]+0x1a2): undefined reference to `std::__open_terminal(_iobuf*)' D:/mingw_msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:/mingw_msys2/ucrt64/include/c++/15.1.0/print:87:(.text$_ZSt14vprint_unicodeP6_iobufSt17basic_string_viewIcSt11char_traitsIcEESt17basic_format_argsISt20basic_format_contextINSt8__format10_Sink_iterIcEEcEE[_ZSt14vprint_unicodeP6_iobufSt17basic_string_viewIcSt11char_traitsIcEESt17basic_format_argsISt20basic_format_contextINSt8__format10_Sink_iterIcEEcEE]+0x3fc): undefined reference to `std::__write_to_terminal(void*, std::span<char, 18446744073709551615ull>)' collect2.exe: error: ld returned 1 exit status 请给出解决方案
最新发布
08-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值