当前位置: 首页 > news >正文

C++ std::string_view介绍及性能提升分析

一、std::string_view简介

std::string_view是C++17引入的一种轻量级的字符串视图类,它提供了一个字符窜的只读视图,而不需要进行内存和复制。它仅持有一个指向字符串数据的指针和一个表示字符串长度的整数,具有如下特点:

  • 只读访问:std::string_view的方法都不会修改原有的字符串,也不会真正的分配内存保存字符串的一部分或者全部。
  • 不拥有字符串数据的所有权:该特性本身不分配内存存储字符串数据。
  • 零拷贝:不会产生字符串的复制拷贝,所以不会产生拷贝这种额外开销。
  • 轻量级:通常只包含一个指针和一个长度,开销很小。
  • 灵活性:可以同时处理C风格字符串、std::string和字符数组。

二、性能提升分析

(一)避免不必要的内存分配和复制操作

std::string_view避免了不必要的内存分配和复制操作,从而提高了性能。例如,在函数参数传递中,使用std::string_view无需进行内存拷贝,而std::string可能涉及深拷贝,这使得std::string_view在参数传递开销上极低。

(二)高效的函数参数传递

std::string_view在函数参数传递中表现出色,特别是在需要频繁传递字符串的场景中。由于它不涉及数据的复制,因此可以显著减少内存使用和提高处理速度。

(三)字符串解析与处理

在解析文本文件或处理网络数据流时,std::string_view可以避免创建大型的字符串拷贝,从而提高程序的性能。例如,在处理日志文件或解析配置文件时,使用std::string_view可以大幅提升性能。

(四)高效的搜索与匹配

std::string_view提供了丰富的成员函数,用于字符串的比较、查找等操作,这些操作在不复制原始数据的情况下进行,提高了效率。

三、使用注意事项

(一)生命周期管理

std::string_view不负责内存管理,使用时需要确保其引用的数据在string_view的生命周期内是有效的,否则可能导致悬空指针或野指针问题。

(二)安全性

虽然std::string_view提供了字符串的长度信息,避免了字符串越界问题,但在使用过程中仍需注意数据的有效性和安全性。

四、示例代码

以下示例代码展示了如何使用 std::string_view 以及它在不同场景下的性能优势:

#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include <chrono>

// 示例1:从不同类型的字符串创建 string_view
void createStringView() {
    // 从 std::string 创建
    std::string str = "Hello, World!";
    std::string_view view1(str);
    std::cout << "view1: " << view1 << std::endl;

    // 从 C 风格字符串创建
    const char* cstr = "C-style string";
    std::string_view view2(cstr);
    std::cout << "view2: " << view2 << std::endl;

    // 从字符数组创建
    const char arr[] = "Character array";
    std::string_view view3(arr, sizeof(arr) - 1); // 注意:手动指定长度
    std::cout << "view3: " << view3 << std::endl;
}

// 示例2:使用 string_view 的成员函数
void useStringViewFunctions() {
    std::string str = "Hello, World!";
    std::string_view view(str);

    // 基本操作
    std::cout << "Length: " << view.length() << std::endl;
    std::cout << "Substring: " << view.substr(7) << std::endl; // "World!"

    // 查找操作
    size_t pos = view.find(',');
    if (pos != std::string_view::npos) {
        std::cout << "Found comma at position: " << pos << std::endl;
    }
}

// 示例3:性能测试 - 函数参数传递
void processString(const std::string& str) {
    // 模拟处理
}

void processStringView(std::string_view view) {
    // 模拟处理
}

void performanceTest() {
    std::string largeString(1000000, 'a'); // 创建一个较大的字符串

    // 测试 std::string 的性能
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000; ++i) {
        processString(largeString);
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "std::string time: " 
              << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() 
              << " us" << std::endl;

    // 测试 std::string_view 的性能
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000; ++i) {
        processStringView(largeString);
    }
    end = std::chrono::high_resolution_clock::now();
    std::cout << "std::string_view time: " 
              << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() 
              << " us" << std::endl;
}

// 示例4:性能测试 - 字符串处理
void parseLogLine(const std::string& line) {
    // 模拟解析日志行
    size_t pos = line.find(' ');
    if (pos != std::string::npos) {
        std::string timestamp = line.substr(0, pos);
        // ...
    }
}

void parseLogLineView(std::string_view line) {
    // 模拟解析日志行
    size_t pos = line.find(' ');
    if (pos != std::string_view::npos) {
        std::string_view timestamp = line.substr(0, pos);
        // ...
    }
}

void stringProcessingTest() {
    std::string logLine = "2023-10-01 12:34:56 INFO Some log message";

    // 测试 std::string 的性能
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000000; ++i) {
        parseLogLine(logLine);
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "std::string processing time: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() 
              << " ms" << std::endl;

    // 测试 std::string_view 的性能
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000000; ++i) {
        parseLogLineView(logLine);
    }
    end = std::chrono::high_resolution_clock::now();
    std::cout << "std::string_view processing time: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() 
              << " ms" << std::endl;
}

int main() {
    createStringView();
    useStringViewFunctions();
    performanceTest();
    stringProcessingTest();

    return 0;
}

代码说明

  1. 创建 std::string_view

    • 可以从 std::string、C 风格字符串或字符数组创建 std::string_view
    • 注意:从字符数组创建时,需要手动指定长度,否则可能会包含多余的字符。
  2. 使用 std::string_view 的成员函数

    • substr:获取子字符串视图(不涉及数据复制)。
    • find:查找字符或子字符串的位置。
  3. 性能测试 - 函数参数传递

    • 比较了 std::stringstd::string_view 作为函数参数时的性能差异。
    • std::string_view 避免了不必要的数据复制,性能更高。
  4. 性能测试 - 字符串处理

    • 模拟解析日志行的场景,比较了 std::stringstd::string_view 的性能。
    • std::string_view 在字符串处理场景中表现更优,因为它避免了创建临时字符串对象。

五、总结

std::string_view作为一种轻量级的字符串处理工具,在只读场景下,特别是在需要高性能的场景下,具有显著的优势。它通过避免不必要的字符串拷贝,提高了程序的性能,同时保持了API的灵活性。在现代C++编程中,合理运用std::string_view,可以在确保性能的同时,提高程序的安全性和灵活性。

相关文章:

  • android面试情景题详解:android如何处理断网、网络切换或低速网络情况下的业务连续性
  • 关于SENSOR 720P/1080P 静电保护方案
  • Python静态方法和类方法详解
  • 在断网的时候,websocket 一直在CLOSING 状态
  • 如何制定合理的项目预算
  • Docker详细使用
  • Windows 系统如何使用Redis 服务
  • 什么是分布式声波传感
  • 性能炸裂的数据可视化分析工具:DataEase!
  • npm 常用命令及示例和解析
  • 位运算题目:连接连续二进制数字
  • python asyncio 的基本使用
  • HTTP 和 HTTPS 协议的区别及使用场景
  • Java微服务流量控制与保护技术全解析:负载均衡、线程隔离与三大限流算法
  • vue3 div 点击右键旁边出现弹窗 可做编辑删除 新增操作
  • 案例-索引对于并发Insert性能优化测试
  • 初阶数据结构--二叉树OJ训练
  • 渗透测试学习-概述
  • 搭载DeepSeek|暴雨AI教育一体机加速AI教育普及
  • # linux 设置宽容模式
  • 中越海警开展2025年第一次北部湾联合巡逻
  • 用8年还原曹操墓鉴定过程,探寻曹操墓新书创作分享会举行
  • 中国旅游日主题月期间,东航将准备超51.9万套特惠机票
  • 87岁老人花3万多做“血液净化”延年益寿?医院“张主任”:我那是善意的欺骗
  • 美国海关新规致跨境包裹延误,DHL暂停超800美元对美个人货运
  • 近千人认购!上海一新盘认购数创今年新高,3月份7个项目开盘“日光”