首页 > 其他分享 >使用 std::string_view 提升字符串处理性能

使用 std::string_view 提升字符串处理性能

时间:2023-12-07 14:46:10浏览次数:31  
标签:std end string tokenizer 字符串 view

C++标准库提供了一个非常优秀的字符串处理类std::string,我们可以通过该类完成各种字符串操作。但是std::string有一个缺点,它的很多操作都是针对字符串实体,存在不必要的内存拷贝的代码,导致字符串的处理性能不尽如人意。

针对这种情况C++17标准引入了std::string_view这个类,该类不会直接作用在字符串实体上,而是记录字符串处理的位置,这样就可以保证用最小的代价对字符串进行处理。

在几个月前写过 std::string_view 的一些简洁介绍,在其中有提及:Here

做函数形参的时候,使用std::string_view基本一定优于老式的const std::string&这种写法。

为了验证这个结论,下面的代码实现了一个断词器,然后针对 \(64MB\) 的数据做断词处理并且分别记录使用std::stringstd::string_view作为基础类型时断词器运行的时间:

#include <iostream>
#include <chrono>
#include <string_view>

template<class T>
struct tokenizer {
    using string_type = T;
    using value_type = typename T::value_type;

    tokenizer(const string_type & str,
              std::enable_if_t<std::disjunction_v<
                      std::is_same<string_type, std::basic_string<value_type>>,
                      std::is_same<string_type, std::basic_string_view<value_type>>>> * = nullptr)
            : data_(str), begin_(0), end_(0) {}

    string_type operator()(const value_type sep) {
        for ( ; end_ < data_.size(); ++end_ )
        {
            if (data_[end_] == sep)
            {
                auto res = data_.substr(begin_, end_ - begin_);
                begin_ = ++end_;
                return res;
            }
        }
        if (end_ <= data_.size())
        {
            return data_.substr(begin_, end_);
        }

        return "";
    }

    bool more() const { return end_ < data_.size(); }

private:
    const string_type data_;
    size_t begin_, end_;
};

auto make_string_data(size_t count, char sep) {
    std::string data;
    for ( size_t i = 0; i < count; ++i )
    {
        data.push_back('a' + i % 26);
        if (i + 1 != count)
            data.push_back(sep);
    }
    return data;
}

int main() {
    auto data = make_string_data(1024 * 1024 * 32, ' ');

    {
        tokenizer<std::string> tk(data);
        auto start = std::chrono::high_resolution_clock::now();
        while ( tk.more())
        {
            tk(' ');
        }
        auto end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> diff = end - start;
        std::cout << "elapsed time = " << diff.count() << std::endl;
    }

    {
        tokenizer<std::string_view> tk(data);
        auto start = std::chrono::high_resolution_clock::now();
        while ( tk.more())
        {
            tk(' ');
        }
        auto end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> diff = end - start;
        std::cout << "elapsed time = " << diff.count() << std::endl;
    }

    return 0;
}

在上面的代码中tokenizer是一个断词器的类模板,接受std::stringstd::wstringstd::basic_string模板实例化的类型,同时也能接受std::string_viewstd::wstring_viewstd::basic_string_view模板实例化的类型。这里采用了SFINAE的方法来约束tokenizer的模板实参必须为以上类型。如果编译环境是C++20标准,可以采用概念来约束模板实参类型。

这份代码tokenizer<std::string>运行结果是0.45秒,如果将tokenizer<std::string>替换为tokenizer<std::string_view>运行时间缩短为0.08秒,性能提升是非常明显的 。

标签:std,end,string,tokenizer,字符串,view
From: https://www.cnblogs.com/RioTian/p/17881949.html

相关文章

  • java 自定义查询StringBuffer Sql
    一、背景二、实现@AutowiredprivateEntityManagerentityManager;Queryquery=entityManager.createNativeQuery(sql);query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);List<Map<String,Object>>reportWaterTota=qu......
  • Spring Boot中的StringUtils:强大的工具类解析
    在实际的业务开发中,除了经常有针对对象的判断或操作以外,经常也会遇到的就是字符串的判断和操作。比如判断字符串是否为空、是否以某个字符结尾、去除头部和尾部的空白字符、字符的查找和替换。在Spring的核心包中存在这样一个类org.springframework.util.StringUtils,它提供了常见的......
  • iview表格行列合并
    官网demo并没有对handleSpan方法进行详细说明demo运行效果如下图可以看到,第一行的第一列和第二列合并,第三行第一列和第四行第一列合并这时,我们再看代码先看 ① 处的代码,rowIndex === 0指的是第一行, columnIndex === 0指的是第一列,rowIndex和columnIndex......
  • Maven无法下载fastdfs-client-java依赖问题解决
    一、分析原因控制台报错具体如下:并且pom.xml中以下依赖爆红:<dependency><groupId>org.csource</groupId><artifactId>fastdfs-client-java</artifactId><version>1.29-SNAPSHOT</version></dependency>原因:因为fastdfs-clien......
  • string 是否线程安全
    线程安全是什么线程安全是指在多线程环境下,程序的执行能够正确地处理多个线程并发访问共享数据的情况,保证程序的正确性和可靠性。typeStringHeaderstruct{Datauintptr//存放指针,其指向具体的存储数据的内存区域Lenint//字符串的长度}并发访问package......
  • Groovy StringBuilder类踩坑
    今天在写脚本的时候发现一个奇怪的错误。经过猜想验证,发现原来Groovy过于灵活了,算是重复踩了之前的坑。Groovy特性描述如下:当Groovy脚本调用getFun()和setFun()方法时,会默认给这个类有一个FunTester的属性。反过来,如果这个类有Fun这个属性,那么get和set方法是不用显式写出来的。本......
  • CF1809D Binary String Sorting 题解
    题意:思路:贪心:单调不降的$01$字符串,一定是一串连续的$0$再加上一串连续的$1$。由于每次操作的代价很大,所以需要在操作次数尽可能少的情况下,尽可能多地使用交换操作。由于$1$次交换操作,只能减少$1$个逆序对,当存在多个逆序对时,优先通过删除操作减少逆序对的......
  • 为什么 idea 建议去掉 StringBuilder,使用“+”拼接字符串
    为什么idea建议去掉StringBuilder,使用“+”拼接字符串目录为什么idea建议去掉StringBuilder,使用“+”拼接字符串1、普通拼接2、循环拼接总结各位小伙伴在字符串拼接时应该都见过下面这种提示:内容翻译:报告StringBuffer、StringBuilder或StringJoiner的任何用法,这些用法......
  • java字符串String类的常用方法
    java字符串String类的常用方法字符串的创建:(1)定义字符串直接赋值,在字符串池中开辟空间()Stringstr1=“Hello”;//在字符串池中写入字符串"hello"Stringstr2=“Hello”;//直接引用字符串池中的"Hello"System.out.println(str1==str2);//地址相同,输出:true(2)使用new关键字......
  • JSON utils 工具类核心方法parseObject , toString实现
    1packagecom.ls.utils;23importjava.lang.reflect.Array;4importjava.lang.reflect.Field;5importjava.util.Arrays;67/**8*@authorLartimes9*@version1.010*@description:JSON工具类11*toJSONString12*parseObject13......