跟我学C++中级篇—string_view分析

一、字符串管理

在前面学习字符串处理时,不外乎是使用char指针或者std::string。但是在C++17推出一个新的字符串相关的类std::string_view。这个在前面分析C++17系列文章中有过应用上的分析和使用。本文将从更深入的从设计思想等各个方面对其进行分析。
std::string_view
std::string_view对c++中的字符串应用来说,是一种内存管理上的进步。在理解上,可以把其理解为数据库中的“视图”。这意味着其只是一种对字符串的表面上的单向映射管理即只可读不可写。正如前面文章的分析,它有些类似于Go语言中的切片。
在标准库中的定义,它是basic_string_view模板类的一个物化实例,描述了“一个能指代 CharT 的常量连续序列的对象,序列首元素在零位置”。更重要的是,它可以兼容多种字符串类型,包括std::string,const char*等等。

二、和string的关系

std::string_view从字面上看,它只比std::string增加了一个view的后缀,因此可以简单理解它只是后者的一个视图。但实际上还是有着很多的细节的不同。主要包括:

  1. 所有权
    二者最明显的不同就是所有权,视图是只能看不能摸的。即string_view只是一个可对字符串指针和长度读操作的接口,而string则完全拥有对字符串数据(内存)的所有操作
  2. 生命周期
    由于所有权的不同,string需要自己管理自己的内存使用生命周期;而string_view则只是一种单向映射,它无法持有映射方的生命周期,一旦对方销毁,则可能形成野指针
  3. 内存管理
    string需要自己进行内存的分配、处理和回收等全过程;string_view则只是使用string对象的指针,不用对内存负责管理
  4. 大小不同
    string通常比较大需要持有开始、结束和容量等属性;而string_view则只有指针和长度,较小
  5. 操作处理
    在一些具体操作,如子串、查找等时,string操作和返回的一个是子串(需要内存拷贝)而string_view返回的是一个指针和长度
  6. 对C风格字符串的处理
    string可以保证提供C风格的字符串结束符\0,而string_view则不保证。从而这就导致通过data()函数操作时,在对字符串结束检查时产生不同的效果。进而导致安全风险的增
  7. 性能
    string由于可能出现内存的开销通常性能是不如string_view的。特别是在处理大字符串或需要频繁的进行字符串拷贝的情况下,更是如此。

明白了二者的不同,就掌握了应用二者的前提,不会出现基础性的错误。

三、分析

在c/c++编程中,字符串的应用是非常普遍的现象。但字符串又不是基础的数据类型,如果字符串小还好一些。当字符串比较大时,传递时的内存管理(分配和回收)就成为了一个开销很大的行为。但在实际情况,往往对数据的读比写多。否则就不会出现很多什么一写多读的锁,表处理等等现象了。
换句话说,字符串的开销大,是指需要分配内存动态分配的情况下。而大量只读情况下,是不需要分配内存的。比如遍历查找、比较等等。
所以string_view的设计目的就是为了满足在只读情况下的高性能使用,防止无效的内存的复制开销等情况。这就是前面提到的,越简单就越安全。但往往简单的场景又多受限制,所以才针对这种简单场景进行了单独的处理。

四、优点和缺点

std::string_view作为一个特定场景下应用接口,是一个优缺点都比较明显的类。其主要的优点包括:

  1. 内存的零拷贝
    在对字符串只读操作时,不需要发生内存的分配管理。特别是大字符串的参数传递时更是如此
  2. 兼容多种字符串
    可以兼容C风格和C++风格等的字符串,便于接口统一
  3. 通用性
    有利于处理字面量和std::string的参数风格统一,避免重载

其缺点也相当明显:

  1. 需要非常谨慎的处理生命周期问题,防止出现野指针。典型的就是指向局部字符串数组时
  2. 无法对指向的数据进行修改
  3. 特别在C风格字符串处理时,要严格处理结尾终止符0的边界检查处理(不保证)

五、使用方法

通过上面的分析,其实已经可以掌握std::string_view的使用方式了。它一般可以用于下列的情况:

  1. 只读性字符串的处理
    这是最典型的应用场景,包括参数传递、临时使用等等情况
  2. 性能敏感的情况
    对于一些性能比较敏感的情况下,可以利用其减少内存开销的特性进行处理。当然,还是需要兼顾不修改字符串本身的前提
  3. 不需要字符串所有权的情况
    这种其实是属于一种更宽泛的使用说明,原则上只要不需要所有权,都可以使用string_view

std::string_view本身的使用并不复杂,只是需要开发者掌握好使用的时机和场景。不要盲目的使用导致意外的情况发生。所以就不再给出相关的示例,如果需要例程可以参看前面的相关文章或在cppreference上查找即可。

六、总结

其实编程的过程就是现实世界中的对待问题的解决的过程。凡事都有普遍和特例。而string和string_view就可以这样的理解。它们既可以统一到一起形成统一的字符串处理问题,又可以分开来展现各自处理场景下的优势问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值