码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • C++ string介绍和坑


    文章目录

      • 一、string原理介绍
        • 1)内部数据结构
        • 2)工作机制(更细节涉及到对应编译器不同平台的具体实现)
          • (1)步骤
          • (2)替代者
      • 二、仅介绍MSVC和GCC编译器对于string的不同实现
      • 三、string的坑
        • 1)C++中string.size()函数 踩坑
        • 2)官网string文档
      • 四、注意点
        • 1)std string是一个char vector,它保存的是自己本身,因此对于ascii字节和宽字节,它需要不同的容器去实现
        • 2)不支持split,find & substr即可解决,何况还有几个加强版的find, 虽然在C++11中,你可以使用更通用的闭包版本来解决,但他的确提供了几个方便又好理解的加强版:find_first_of, find_last_of, find_first_not_of, find_last_not_of;
        • 3)C++11明确规定了字符串以\0结尾了。为的是data()能兼容c风格字符串
        • 4)string是模板的标准库,effectiveC++不建议继承
        • 5)copy_on_write与多线程有安全问题.
        • 6)std::string无法作为dll接口参数

    一、string原理介绍

    1)内部数据结构

    ①三指针(类似vector)
    (1)数据起始段,begin of the allocated region and data
    (2)数据终止段,end of data
    (3)数据存到现在buffer的哪个位置了, a pointer (begin of allocated region and data)
    ②两整数:
    (1)存储字母的数量,number of characters in the string
    (2)分配buffer的字节数,number of allocated bytes

    2)工作机制(更细节涉及到对应编译器不同平台的具体实现)

    (1)步骤

    0)一开始若小于24字节,就默认分配24字节的内存区域
    1)当新赋值字符串,如果分配的内存还有余额或整块内存都可以放得下字符串数据,那么就在第三个指针后面更新数据;
    2)当余额buffer内存不够来存储了,那就动态分配更多内存来字符串,有的说是1.5倍所需内存或2倍所需内存,than the alternative of growing by a single allocation block.,然后把自己的原先内容拷贝过去

    • 缺点
      因为要从原先的地方拷贝,所以效率不好
    (2)替代者

    一个是 Facebook folly 出品的 FBString ,另一个是 Google 出品的 StringPiece,例如 leveldb 中的 Slice

      1. StringPiece什么是 StringPiece ?A string-like object that points to a sized piece of memory说白了就是string的只读视图,为了便于解释,直接来看代码吧:void func(const std::string & str);
        const & 限定了 函数 func 没法修改入参 str,但是如果给 func 传递的参数是 char * 或者 const char *,那么将构造一个临时的 std::string,并且产生了字符串的拷贝,但是显然这次拷贝并没有必要。StringPiece 就是在这种情况去替换 std::string,可以避免字符串拷贝,因为 StringPiece 只是简单接管一下指针,看一下 StringPiece 的简单实现就知道了,这里以 leveldb 中的 Slice 为例子,看一下其构造函数就明白了
    class LEVELDB_EXPORT Slice {
     public:
      ......
      Slice(const char* d, size_t n) : data_(d), size_(n) { }
      ......
     private:
      const char* data_;
      size_t size_;
    };    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
      1. FBStringFBString 是 facebook 开源 C++ lib folly 的一个 std::string 替换着,如果你想更好的性能,又不想重写,那么 FBString 是一个不错的选择,Facebook 对其做了大量的性能优化,其核心特点如下:100% 兼容 std::string高性能的内存管理,对不同大小的字符串, 分 3 种情况分配和管理内存:

    (1)string length <= 23,使用栈上内存;
    (2)23< string length <=255,使用 malloc 分配堆上内存;
    (3)string lenght > 255,堆上内存,且使用引用计数 + COW 计数,实现在真正需要的时候才拷贝修改,避免大字符串不必要的拷贝find 操作使用了 Boyer Moore [3] 算法,

    • 性能
      相比 O(n) 的 KMP 实际性能好很多,Facebook 官方宣称性能:Casual tests indicate a 30x speed improvement overstring::find()for successful searches and a 1.5x speed improvement for failed searches感兴趣的可以去了解使用下。实际上没有最好,只有最合适,就看 std::string 是否满足你的需求

    二、仅介绍MSVC和GCC编译器对于string的不同实现

    • gcc
      gcc4.8.5之前都是COW,
    • MSVC
      MSVC debug下无任何优化,release下是SSO
    • SSO解释
      SSO是短/小字符串优化。 std::string 通常,A 将字符串存储为指向免费存储区(“堆”)的指针,该存储区具有与调用相似的性能特征 new char [size] 。 这样可以防止非常大的字符串出现堆栈溢出,但是这样做可能会更慢,尤其是对于复制操作而言

    三、string的坑

    1)C++中string.size()函数 踩坑

    • 原因
      例如string、vector等类型的size函数返回的是一个无符号整型数
    • 解释
      带符号数将自动转换为无符号数,例如-1,由于-1的二进制表示的最高位为1,这回导致size() > -1一定会返回false。在进行判断size()时,还是应该使用0进行比较。
    • 错误实例
    #include
    #include
    using namespace std;
    
    int main(){
    	string haystack = "";
    	string needdle = "a";
    	int i=0;
    	cout<<haystack.size()<<endl;
    	cout<<needdle.size()<<endl;
    	cout<<haystack.size()-needdle.size();
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    haystack的长度为0,needle的长度为1,而 无符号的 0减1 时出现了如下情况

    • 结果
      在这里插入图片描述

    2)官网string文档

    传送门

    四、注意点

    1)std string是一个char vector,它保存的是自己本身,因此对于ascii字节和宽字节,它需要不同的容器去实现

    2)不支持split,find & substr即可解决,何况还有几个加强版的find, 虽然在C++11中,你可以使用更通用的闭包版本来解决,但他的确提供了几个方便又好理解的加强版:find_first_of, find_last_of, find_first_not_of, find_last_not_of;

    3)C++11明确规定了字符串以\0结尾了。为的是data()能兼容c风格字符串

    4)string是模板的标准库,effectiveC++不建议继承

    5)copy_on_write与多线程有安全问题.

    6)std::string无法作为dll接口参数

  • 相关阅读:
    Allegro DFM Ravel Rule 丝印文字到PAD 间距检查
    [BDOI Round 1] 题解
    DOM常用方法以及项目
    leetcode-627. 变更性别
    JVM:(十四)垃圾回收算法
    虚拟展厅三维交互体验满足用户多场景营销需求
    改进YOLOv8:结合ODConv构成C2f_ODConv:即插即用的动态卷积/可轻量化
    scrm系统哪款好?快鲸scrm私域流量运营专家
    宏观经济学通识课-读书笔记
    SpringMVC之JSON返回&异常处理机制
  • 原文地址:https://blog.csdn.net/weixin_43679037/article/details/127536657
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号