andorid view如何附带数据_第15篇:高效的字符串视图(string_view)

string对象的性能问题

了解string对象的内存分配行为后,接下来我们如何考虑使用什么方法来避免字符串频繁的拷贝,有些经验的“老油条”应该都领略过了const string&这类参数类型声明并不能从根本上解决问题(上一篇文章的程序输出已经隐藏地说明了这一点),因为按引用传参仅能避免了参数传递的字符串拷贝,但在被调用函数内部,只要涉及string对象赋值操作,string内部仍然执行拷贝依然存在,特别是大字符串的赋值操作会触发堆内存分配,我们知道堆内存管理是一个高时间成本消耗的操作。

C++的string对象,如果大于默认的字符串长度阀值。对于长度为N的字符串,时间成本为O(n),空间成本是2xS(n);

于是C++17就有了string_view这个标准库的扩展,这个扩展极大地解决了string拷贝的空间成本和时间成本问题。我们本篇要介绍的是string_view是C++程序猿在处理字符串操作的一大福音。因为string_view基本没有涉及内存的额外分配。

#include <string>
#include <iostream>
#include <string_view>

void* operator new(std::size_t count){
  std::cout<<"分配了堆内存"<<count<<"字节."<<std::endl;
  return malloc(count);
}

void operator delete(void* p){
   std::cout<<"释放堆内存:"<<p<<std::endl;
   free(p);
}

void show_str(const std::string &str){
   std::cout<<std::endl;
   std::cout<<"show_str()临时变量tmp初始化"<<std::endl;
   std::string tmp=str;
   printf("str副本的地址:%pn",str.c_str());
   printf("tmp副本的地址:%pn",tmp.c_str());
}

void show_stv(std::string_view stv){
   printf("string_view对象str的内部地址:%pn",stv.data());
}

int main(void){
  std::cout<<std::endl;
  std::cout<<"-------初始化string对象-------"<<std::endl;
  std::string you="How do you do~,My name is peter!";
  std::cout<<std::endl;
  
  std::cout<<"-------初始化string_view对象-------"<<std::endl;
  std::string_view stv(you.c_str(),you.size());
  std::cout<<std::endl;
  std::cout<<"---------show_str---------"<<std::endl;
  printf("main函数:you副本中的字符串地址:%pn",you.c_str());
  show_str(you);

  std::cout<<std::endl;
  std::cout<<"字符串字面量直接传参方式"<<std::endl;
  show_str("How do you do~,My name is peter!");

  std::cout<<std::endl;
  std::cout<<"---------show_stv----------"<<std::endl;
  std::cout<<std::endl;
  std::cout<<"字符串字面量直接传参方式"<<std::endl;
  show_stv(stv);

  std::cout<<std::endl;
  std::cout<<"数组字符串传参方式"<<std::endl;
  show_stv("How do you do~,My name is peter!");

  std::cout<<std::endl;

  return 0; 
}

程序输出:

43e93d0799b0d33fe9b04738be6bb3b4.png

到这里我们从上图程序输出可以发现,string_view对象从初始化到打印几次调用show_stv()函数都无法涉及触发new操作,并且因为string_view实际上不持有字符串副本,因此string_view从空间成本和时间成本远远胜于string对象。

因为string_view内部的私有数据成员_M_str是一个类似C版本的char*指针,该私有数据成员指向初始化string_view构造函数的字符串副本的地址。我们向被调用函数传递string_view类型的参数,你可以不科学d地因为认为如下类似的代码是相当的

show_stv(std::string_view) 

效果相当于

show_stv(char*) 

因为它们涉及赋值操作的时间成本是O(1),另外,string_view内部并不持有一个字符串副本 ,所以涉及空间消耗可以认为S(1).

string_view的适用场合

由于string_view对象无法被使用它的函数修改,因此要更新string_view所引用的字符串副本,还是需要修改它所引用的string类型的内部字符串副本。

  • 字符串查找
  • 遍历字符串
  • 显示字符串

结语

我这里并不打算罗列一大堆string_view的api,因为没必要,你要掌握它的基本用法,只要熟悉string对象,掌握string_view自然不是问题。你也可以参考其他相关的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值