`std::string_view`(c++17) 和 `std::stringstream` 使用区别·
std::string_view 和 std::stringstream 都是 C++ 中处理字符串的工具,但它们的设计目标和使用场景非常不同。我们可以通过几方面进行对比。
1. 设计目的和核心功能
std::string_view:- 设计用于只读访问字符串或字符序列。
- 是一个轻量级的字符串视图,不会持有字符串的数据,仅仅是对现有字符串的引用。
- 适合高效地操作已有字符串或进行快速读取(例如子串操作、比较等),没有额外的内存分配。
std::string_view是 C++17 引入的一种轻量级的字符串视图类型,它提供了一种非常高效的方式来引用和操作现有的字符串(或字符数组)而不需要复制数据。
什么是 std::string_view
std::string_view 本质上是一个不可变的字符串引用,它可以指向现有的字符串数据(例如 std::string、C 风格的字符串数组等),而不实际拥有这些数据。
它的作用是让你能够高效地查看或操作某个字符串的子集,而不必进行额外的内存分配或数据拷贝。
为什么使用 std::string_view
- 避免不必要的拷贝: 传统的
std::string在传递和处理时通常会复制数据,而std::string_view仅仅是一个对已有字符串的引用,避免了数据的复制和重新分配,提高了性能。 - 适用于
只读操作: 如果你只需要读取字符串的内容而不需要修改,std::string_view是一个很好的选择。 - 兼容性:
std::string_view可以直接从std::string或 C 风格字符串创建,并且使用起来十分灵活。 - 子串操作效率高: 使用
std::string_view可以轻松地处理字符串的子串而不引起额外的内存分配。
std::string_view 的基本用法
#include <iostream>
#include <string>
#include <string_view>
int main() {
// 从 C 风格字符串创建 string_view
const char* cstr = "Hello, World!";
std::string_view sv1(cstr);
// 从 std::string 创建 string_view
std::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_view
for (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::string_view 是 C++17 引入的一个轻量级字符串类,用于表示字符串的视图而不实际复制字符串。它的 substr 方法用于获取指定范围内的子字符串视图。
方法原型
std::string_view substr(size_type pos = 0, size_type count = npos) const noexcept;
参数
pos:起始位置,默认为0。count:要提取的字符数,默认为npos(即直到字符串结束)。
返回值
返回一个新的 std::string_view,表示从 pos 开始的 count 个字符。
使用示例
#include <iostream>
#include <string_view>
int main() {
std::string_view str = "Hello, World!";
// 获取从索引 7 开始的子字符串
std::string_view subStr = str.substr(7);
std::cout << "Substring: " << subStr << std::endl; // 输出 "World!"
// 获取从索引 0 开始的 5 个字符
std::string_view subStr2 = str.substr(0, 5);
std::cout << "Substring: " << subStr2 << std::endl; // 输出 "Hello"
return 0;
}
- 边界检查:如果
pos超过std::string_view的长度,会导致未定义行为。可以使用size()方法来确保pos是有效的。 - 不进行拷贝:
std::string_view并不持有字符串的所有权,因此它的生命周期与原始字符串相关联。如果原始字符串在std::string_view被使用后被销毁,将导致悬挂引用。 - 性能优势:使用
std::string_view可以避免不必要的字符串拷贝,适合在需要频繁操作字符串的情况下使用。
长度:
std::size_t len = sv.length(); // 获取字符串的长度
访问元素:
char first_char = sv[0]; // 访问第一个字符
比较:
if (sv == "Hello") {
// 相等
}
注意事项
- 寿命管理:
std::string_view不拥有其指向的数据,因此必须确保它指向的字符串在std::string_view使用期间有效。否则会导致悬空引用的问题。 - 不可修改:
std::string_view是只读的,不能修改它指向的字符串内容。如果需要修改,应该使用std::string或其他可变的字符串类型。
std::stringstream:- 设计用于字符串的读写操作,类似于内存中的字符流(和
std::cin或std::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适合的场景:- 需要对字符串进行格式化、拼接、插入、修改等操作。
- 需要将数据从其他类型(如
int、double等)转换为字符串,或从字符串中提取数据。
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 则是更好的选择。
`std::string_view`(c++17) 和 `std::stringstream` 使用区别·的更多相关文章
- could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
VS2008, 写一个简单的demo的时候出现了这个: 1>------ Build started: Project: GetExportTable, Configuration: Relea ...
- std::u32string conversion to/from std::string and std::u16string
I need to convert between UTF-8, UTF-16 and UTF-32 for different API's/modules and since I know have ...
- c++11 标准库函数 std::move 和 完美转发 std::forward
c++11 标准库函数 std::move 和 完美转发 std::forward #define _CRT_SECURE_NO_WARNINGS #include <iostream> ...
- C++17剖析:string_view的实现,以及性能
主要内容 C++17标准发布,string_view是标准新增的内容.这篇文章主要分析string_view的适用范围.注意事项,并分析string_view带来的性能提升,最后从gcc 8.2的li ...
- C++17中那些值得关注的特性(上)
C++17标准在2017上半年已经讨论确定,正在形成ISO标准文档,今年晚些时候会正式发布.本文将介绍最新标准中值得开发者关注的新特新和基本用法. 总的来说C++17相比C++11的新特性来说新特性不 ...
- Nginx学习笔记(四):基本数据结构
目录 Nginx的一些特点 Nginx自定义整数类型 异常机制错误处理 内存池 字符串 时间与日期 运行日志 Nginx的一些特点 高性能 采用事件驱动模型,可以无阻塞的处理海量并发连接 高稳定性 ...
- C++20协程实例:携程化的IOCP服务端/客户端
VC支持协程已经有一段时间了,之前一直想不明白协程的意义在哪里,前几天拉屎的时候突然灵光一闪: 以下是伪代码: task server() { for (;;) { sock_context s = ...
- boost::property_tree读取解析ini文件--推荐
boost::property_tree读取解析ini文件 #include "stdafx.h" #include <iostream> #include <b ...
- boost.xml_parser中文字符问题
当使用xml_parser进行读xml时,如果遇到中文字符会出现解析错误. 网上有解决方案说使用wptree来实现,但当使用wptree来写xml时也会出错.而使用ptree来写中文时不会出错. 综合 ...
- 使用boost中的property_tree实现配置文件
property_tree是专为配置文件而写,支持xml,ini和json格式文件 ini比较简单,适合简单的配置,通常可能需要保存数组,这时xml是个不错的选择. 使用property_tr ...
随机推荐
- 在Django REST framework (DRF) 中,`request.query_params` 和 `request.data` 区别
在Django REST framework (DRF) 中,request.query_params 和 request.data 都是用来获取请求中的数据,但是它们之间有一些关键的区别: requ ...
- web3 产品介绍:metamask 钱包 使用dapp更方便的钱包
Metamask钱包是一种基于区块链技术的数字货币钱包,它允许用户在安全.便捷的环境下管理自己的加密资产.Metamask钱包是以太坊生态系统中最流行的钱包之一,它具有易于使用.安全性高和功能强大等优 ...
- 【SpringBoot】01 快速上手
环境搭建: JDK8 + IDEA 2018 + SpringBoot + Maven 3.0 + 创建Boot项目 2020.6.1更新补充: 最近才发现SpringBoot用IDEA构建项目会发生 ...
- 2024年是否是人形机器人的元年 —— 继OpenAI/Google/特斯拉之后黄仁勋也宣布NVIDIA公司的人形机器人项目 —— Groot项目 —— 英伟达公布了人形机器人项目 GR00T
相关: https://www.youtube.com/watch?v=bMIRhOXAjYk 参考: https://www.thepaper.cn/newsDetail_forward_26730 ...
- 【转载】 【WarpDrive】GPU加速RL: 一块V100运行上千个智能体、数千个环境,这个「曲率引擎」框架实现RL百倍提速
原文地址: https://mp.weixin.qq.com/s/Vw39k2PteEIGLRhmh2raLQ ============================================ ...
- 2023年 IJCAI 审稿模板
================================================== ================================================= ...
- 再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(6) —— Python版本实现的《2048》游戏环境运行性能对比
<2048>游戏在线试玩地址: https://play2048.co/ 如何解决<2048>游戏源于外网的一个讨论帖子,而这个帖子则是讨论如何解决该游戏的最早开始,可谓是&q ...
- PKUSC2019 D1T1 题解
前言 五一网课的例题,但是网上没有详细的题解(其实就是都没放代码),所以来写一篇,就当攒 RP 了.题目可以在这里(不强制在线)或这里(强制在线)提交. 题目简述 有 \(n\)(\(n \leq 5 ...
- 亚信科技基于 Apache SeaTunnel 的二次开发应用实践
亚信科技在Apache SeaTunnel的实践分享 自我介绍 各位同学好,很荣幸通过Apache SeaTunnel社区和大家进行分享交流.我是来自亚信科技的潘志宏,主要负责公司内部数据中台产品的开 ...
- 记一次解决OTA死机重启bug,如何分析与解决措施?!
背景: 平台:stm32mp151平台 什么是OTA? 说起OTA我们应该都不陌生,它是一种可以为设备无损失升级系统的方式,能将新功能远程部署到产品上. 我们不仅可以通过网络下载OTA升级包,也可以通 ...