`std::string_view`(c++17) 和 `std::stringstream` 使用区别

news/2024/9/23 15:25:57/文章来源:https://www.cnblogs.com/niumachen/p/18427126

std::string_viewstd::stringstream 都是 C++ 中处理字符串的工具,但它们的设计目标和使用场景非常不同。我们可以通过几方面进行对比。

1. 设计目的和核心功能

  • std::string_view:
    • 设计用于只读访问字符串或字符序列。
    • 是一个轻量级的字符串视图,不会持有字符串的数据,仅仅是对现有字符串的引用。
    • 适合高效地操作已有字符串或进行快速读取(例如子串操作、比较等),没有额外的内存分配。
      std::string_view 是 C++17 引入的一种轻量级的字符串视图类型,它提供了一种非常高效的方式来引用和操作现有的字符串(或字符数组)而不需要复制数据。

什么是 std::string_view

std::string_view 本质上是一个不可变的字符串引用,它可以指向现有的字符串数据(例如 std::string、C 风格的字符串数组等),而不实际拥有这些数据。
它的作用是让你能够高效地查看或操作某个字符串的子集,而不必进行额外的内存分配或数据拷贝。

为什么使用 std::string_view

  1. 避免不必要的拷贝: 传统的 std::string 在传递和处理时通常会复制数据,而 std::string_view 仅仅是一个对已有字符串的引用,避免了数据的复制和重新分配,提高了性能。
  2. 适用于只读操作: 如果你只需要读取字符串的内容而不需要修改,std::string_view 是一个很好的选择。
  3. 兼容性: std::string_view 可以直接从 std::string 或 C 风格字符串创建,并且使用起来十分灵活。
  4. 子串操作效率高: 使用 std::string_view 可以轻松地处理字符串的子串而不引起额外的内存分配。

std::string_view 的基本用法

#include <iostream>
#include <string>
#include <string_view>int main() {// 从 C 风格字符串创建 string_viewconst char* cstr = "Hello, World!";std::string_view sv1(cstr);// 从 std::string 创建 string_viewstd::string str = "Hello, C++!";std::string_view sv2(str);// 输出 string_view 的内容std::cout << "String view 1: " << sv1 << std::endl;std::cout << "String view 2: " << sv2 << std::endl;// 获取子串 (不分配新内存)std::string_view sv3 = sv2.substr(0, 5); // "Hello"std::cout << "Substring view: " << sv3 << std::endl;// 遍历 string_viewfor (char ch : sv3) {std::cout << ch << ' ';}std::cout << std::endl;return 0;
}

常用操作

  • 构造:

    std::string_view sv1("Hello");  // 从 C 字符串构造
    std::string_view sv2(str);      // 从 std::string 构造
    
  • 子串操作:

    std::string_view sv = "Hello, C++!";
    std::string_view sub_sv = sv.substr(0, 5);  // 获取 "Hello"
    
  • 长度:

    std::size_t len = sv.length();  // 获取字符串的长度
    
  • 访问元素:

    char first_char = sv[0];  // 访问第一个字符
    
  • 比较:

    if (sv == "Hello") {// 相等
    }
    

注意事项

  1. 寿命管理: std::string_view 不拥有其指向的数据,因此必须确保它指向的字符串在 std::string_view 使用期间有效。否则会导致悬空引用的问题。
  2. 不可修改: std::string_view 是只读的,不能修改它指向的字符串内容。如果需要修改,应该使用 std::string 或其他可变的字符串类型。
  • std::stringstream:
    • 设计用于字符串的读写操作,类似于内存中的字符流(和 std::cinstd::cout 类似)。
    • 持有字符串数据,能够进行字符串的格式化操作(如插入、提取等)。
    • 适合动态生成或修改字符串的场景,比如构建一个复杂的字符串或从字符串中提取特定类型的数据。

2. 性能比较

  • std::string_view:

    • 高效:不进行内存拷贝或数据持有,操作时间复杂度通常为常数时间。
    • 适用于只读访问已有字符串,非常适合处理子串或无需修改的字符串。
    • 缺点:只能对已有的字符串或字符数组操作,不能修改数据或进行复杂的字符串拼接等操作。
  • std::stringstream:

    • 灵活:可以动态构建、修改和操作字符串。
    • 相对较慢:由于 std::stringstream 需要动态分配内存并持有数据,在处理大量数据时会有性能开销。
    • 缺点:不适合只读访问已有的字符串。它的设计目标是进行读写和格式化操作。

3. 使用场景

  • std::string_view 适合的场景:

    • 高效读取已有字符串(比如处理输入字符串的子串)。
    • 解析静态字符串或从已有的数据块中获取特定内容。
    • 只需要读取,而不需要修改字符串的地方,尤其是在性能敏感的场合。
    std::string_view sv("Hello, World!");
    if (sv.substr(0, 5) == "Hello") {std::cout << "Substring match!" << std::endl;
    }
    
  • std::stringstream 适合的场景:

    • 需要对字符串进行格式化、拼接、插入、修改等操作。
    • 需要将数据从其他类型(如 intdouble 等)转换为字符串,或从字符串中提取数据。
    std::stringstream ss;
    ss << "Number: " << 42 << ", Float: " << 3.14;
    std::string result = ss.str();  // "Number: 42, Float: 3.14"
    

4. 数据所有权和内存管理

  • std::string_view:

    • 不拥有字符串的所有权,只是对现有字符串的引用。用户需要确保引用的字符串在 string_view 的生命周期内有效。
    • 由于它不拷贝数据,内存管理效率很高。
  • std::stringstream:

    • 持有字符串数据,意味着它会管理数据的内存分配和释放。在进行复杂的字符串拼接和操作时,可能会引起多次内存分配和拷贝。

5. 字符串修改

  • std::string_view:

    • 不允许修改字符串,因为它是一个只读视图。只能访问而不能更改内容。
  • std::stringstream:

    • 允许修改字符串,可以向流中添加、删除或提取数据。

6. 代码对比

  • std::string_view 例子(只读访问):

    std::string str = "Hello, World!";
    std::string_view sv(str);
    std::cout << sv.substr(7, 5);  // 输出: "World"
    
  • std::stringstream 例子(读写操作):

    std::stringstream ss;
    ss << "Hello, " << "World!";
    std::string result = ss.str();  // result 是 "Hello, World!"
    

7. 总结

  • std::string_view 是高效处理只读字符串的工具,适用于不需要修改数据的场合,主要用于提高性能。
  • std::stringstream 则是用于处理字符串的动态操作,如格式化、拼接、转换等,适合需要读写字符串的场景。

根据实际需求选择合适的工具。如果你只需要高效读取字符串内容而不修改,std::string_view 更合适;如果你需要操作或构造字符串,std::stringstream 则是更好的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/802221.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css使用@media响应式适配各种屏幕的方法示例

定义和使用 使用 @media 查询,你可以针对不同的媒体类型定义不同的样式。 @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。 当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。 PC端设备…

多智能体协同控制(1)

引言 多智能体系统协同控制算法起源于计算机领域关于分布式计算的研究,后由于数学家们的强势加盟,控制领域的研究一度占领高地。随着人工智能的发展,以多智能体强化学习为代表作的计算机领域专家又重回巅峰。 目前,每年多智能体相关的论文的都浩如烟海,成就了一批手持屠龙…

Axure原型设计:多层级动态表格

多层级表格又成为树形表格,是在后台常用的一种表格形式,当表格数据存在多层级关系是,可以通过多层级表格,从而更加清晰的呈现数据内容,帮助人们更好地理解和分析数据之间的关系,从而更加有效地传递信息。 所以今天作者就教大家怎么在Axure里制作多层级动态表格,包括展开…

frp内网穿透 宝塔部署服务端、客户端教程

宝塔部署教程链接:https://blog.csdn.net/m0_57944649/article/details/140693257 frp官方下载链接:https://github.com/fatedier/frp/releases一、部署服务端1、上传好文件后解压2、进入解压好了的文件夹“frp_0.58.1_linux_amd64”中,找到文件“frps.toml”,双击打开: …

建立数据库连接时出现错误:原因与解决方案

建立数据库连接时出现错误的原因可能有很多,以下是一些常见的原因及其解决方案: 原因登录信息错误:账号、密码、服务器名称或数据库名称不正确。网络问题:客户端与数据库服务器之间的网络连接不稳定或中断。数据库服务未启动:数据库服务没有运行,或者在尝试连接时服务停止…

数据库连接失败的解决方法有哪些

当遇到数据库连接失败的情况时,可以按照以下步骤进行排查和解决:检查数据库服务状态:确认数据库服务是否已启动并运行正常。可以使用阿里云控制台的服务监控工具或通过SSH登录服务器,使用命令行工具(如service mysqld status)来检查服务状态。验证网络连接:确保你的应用…

数据库常见十大错误_数据库十大报错语句

数据库操作时可能会遇到各种错误,这些错误通常是由不同的原因引起的,比如语法错误、连接问题、权限问题等。下面是数据库操作中常见的几种错误类型及其解决思路:连接失败:错误信息可能包括“无法连接到主机”、“连接被拒绝”等。检查数据库服务是否启动、网络连接是否正常…

阿里云主机数据库链接失败怎么回事

阿里云主机数据库连接失败的问题可能有多种原因,这里列举了一些常见的原因及解决办法:网络问题:确认你的网络连接是否正常。尝试使用其他设备或网络连接来验证问题是否出在网络方面。防火墙设置:确保防火墙没有阻止数据库连接。可以尝试临时禁用防火墙,或添加相应的规则来…

收藏:加不加「/」?Nginx location 路径与 proxy_pass 的规律

从一张梗图开始 起源于在 TG 某个频道看到的一张图:图下面的评价是:Nginx is so hard! 实际上这张图描述的是 nginx location 的路径配置,及 location 代码块中 proxy_pass 的路径关系,属于 nginx 应用中路径转发的知识。例如图中 Case 1 对应的代码块应该为:location /te…

直接通过修改二进制文件OpenSSH和OpenSSL的版本为最高版版本来达到形式主义等保要求的操作

文章开头的解释和说明本篇文章是通过形式上修改二进制文件中的版本号来达到某些像行尸走肉机器人类形式主义要求的等保标准要求,来完成其要求的“安全加固”。 我先吐槽一下,这些形式主义等保标准要求,只按照版本号比对来确定是否为最版本的检测逻辑来批量扫描,扫描出来的漏…

Nuxt Kit 使用日志记录工具

title: Nuxt Kit 使用日志记录工具 date: 2024/9/23 updated: 2024/9/23 author: cmdragon excerpt: 摘要:本文介绍在Nuxt 3框架的Nuxt Kit中使用日志记录工具的方法,重点讲解useLogger函数的应用,通过创建示例项目一步步展示如何配置和使用日志记录功能来监控应用状态、记…