• C++(17):string_view


    当我们使用string类时,通常会堆内存的分配:

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4. void* operator new(size_t count)
    5. {
    6. cout << "new " << count << " bytes" << endl;
    7. return malloc(count);
    8. }
    9. int main()
    10. {
    11. cout<<"init s1"<<endl;
    12. string s1 = "123456789";
    13. cout<<"init s2"<<endl;
    14. string s2 = "abcdefghijklmnopqrstuvwxyz";
    15. cout<<"init s3"<<endl;
    16. string&& s3 = s2.substr(5);
    17. return 0;
    18. }
    19. 运行程序输出:
    20. init s1
    21. init s2
    22. new 27 bytes
    23. init s3
    24. new 22 bytes

    可见,当使用string时有时是在堆上分配的内存,有时却不是。

    这个是根据字符串的长度来决定的,当字符串的长度(含结束符)小于等于16时,字符串实际上被存储在string对象内部。但是当字符串的长度大于16时,string会在堆上分配内存空间,来存储字符串。

    同时成员函数substr也会返回一个string对象,该对象也会依据上述原则来选择存储字符串的方式。

    这样管理字符串的方式,如果对于只是读取字符串,那么不免有些效率上的浪费。

    虽然我们可以采用传递引用string的方式,减少不必要的内存分配,但这种方式仅对string对象有效,对于char*是失效的。

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4. void* operator new(size_t count)
    5. {
    6. cout << "new " << count << " bytes" << endl;
    7. return malloc(count);
    8. }
    9. void pStr(int i, const string& s)
    10. {
    11. cout<<i<<" pStr s:"<<s<<endl;
    12. }
    13. int main()
    14. {
    15. pStr(1, string("1234567890"));
    16. pStr(2, "abcdefghijklmnopqrstuvwxyz");
    17. return 0;
    18. }
    19. 运行程序输出:
    20. 1 pStr s:1234567890
    21. new 27 bytes
    22. 2 pStr s:abcdefghijklmnopqrstuvwxyz

    当通过char*的方式传递参数时,会首先根据char*构造出一个string对象来,然后再将其传递个string&。这种方式还是会造成堆内存的分配。

    C++17增加了string_view类,用于更高效的读取字符串。

    string_view可以认为是string/char*的一个代理类,他可以观察对应的字符串,但不允许对其进行修改。

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4. void* operator new(size_t count)
    5. {
    6. cout << "new " << count << " bytes" << endl;
    7. return malloc(count);
    8. }
    9. void pStr(int i, string_view s)
    10. {
    11. cout<<i<<" pStr s:"<<s<<endl;
    12. }
    13. int main()
    14. {
    15. pStr(1, string("1234567890"));
    16. pStr(2, "abcdefghijklmnopqrstuvwxyz");
    17. return 0;
    18. }
    19. 运行程序输出:
    20. 1 pStr s:1234567890
    21. 2 pStr s:abcdefghijklmnopqrstuvwxyz

    可见,使用string_view没有堆内存的分配。

    对于需要修改string_view的字符串的地方,可以将其转换为string后再修改:

    1. #include <string>
    2. #include<iostream>
    3. using namespace std;
    4. int main()
    5. {
    6. string_view a = "12345";
    7. string b = a.data();
    8. b += "67890";
    9. cout << a << endl; //输出:12345
    10. cout << b << endl; //输出:1234567890
    11. return 0;
    12. }

    需要注意的是对于其成员函数substr的使用:

    1. #include <string>
    2. #include<iostream>
    3. using namespace std;
    4. int main()
    5. {
    6. string_view a = "12345";
    7. string_view b = a.substr(1, 2);
    8. cout<<b<<endl; //输出:23
    9. string c = b.data();
    10. cout<<c<<endl; //输出:2345
    11. return 0;
    12. }
    13. string_view的substr可以类似string.substr一样返回一个新的视图。
    14. 但是当对这个新的视图获取其data时,实际上是返回的从视图的起点一直到原始字符串结束的所有字符。

  • 相关阅读:
    常见文件编码 - 多字节编码与Unicode编码区别
    【Confluence】预览中文附件出现乱码,离线Linux下安装字体
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    Spring Boot集成RabbitMQ快速入门Demo
    146. LRU 缓存
    MySQL:互联网公司常用分库分表方案汇总
    一、综合——通信职业道德
    不懂就学—什么是autoML?
    16.希尔排序
    eureka单节点搭建以及集群的搭建
  • 原文地址:https://blog.csdn.net/jiemashizhen/article/details/125628779