第4篇:C++ 高效的string_view

作者: 铁甲万能狗 | 来源:发表于2019-11-06 15:09 被阅读0次

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副本的地址:%p\n",str.c_str());
   printf("tmp副本的地址:%p\n",tmp.c_str());
}

void show_stv(std::string_view stv){
   printf("string_view对象str的内部地址:%p\n",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副本中的字符串地址:%p\n",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; 
}

程序输出:


到这里我们从上图程序输出可以发现,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自然不是问题。你也可以参考其他相关的文章。

相关文章

  • 第4篇:C++ 高效的string_view

    string对象的性能问题 了解string对象的内存分配行为后,接下来我们如何考虑使用什么方法来避免字符串频繁的...

  • C++ 17:string_view

    为什么要增加string_view?考虑一下这种场景,我们有一个字符串,然后我们想获取这个字符串的一个子串,然后对...

  • string_view

    C++的string_view相当于两根指针。有点类似go语言的slice。它指向一个字符串。string_vie...

  • 《Effective C++》

    再读高效c++,颇有收获,现将高效c++中的经典分享如下,希望对你有所帮助。 1、尽量以const \enum\i...

  • C++远征之起航篇

    C++和C语言的联系与区别: C++是C语言发展而来,C语言是C++的子集 C++更高效3.相对于C语言,C++添...

  • c++ ffi

    我的服务器引擎使用c++/lua。 希望利用到luajit的高效,同时去掉c++绑定(luabridge)。因此我...

  • Effective C++ 学习备忘录一

    让自己习惯 C++ 条款 01 - 视 C++ 为一个联邦 请记住 C++ 高效编程守则视状况而变化,取决你用 C...

  • C++程序设计入门(上) 崔毅东

    Introduction to C++ (Season 1) Unit 1: Overview of C++ 第1...

  • [C++ 语言入门到精通] 目录大纲

    第1章 C++简介和历史 第2章 进入C++的世界 第3章 数据类型和运算符 第4章 复合类型 第5章 循环控制和...

  • 读书笔记 | Effective C++:改善程序与设计的55个

    PART0、前言 TOPIC运用c++进行高效编程 收获了解c++如何行为为什么那样行为如何运用其行为形成优势 P...

网友评论

    本文标题:第4篇:C++ 高效的string_view

    本文链接:https://www.haomeiwen.com/subject/skchbctx.html