C++字符串拼接的效率问题

文章目录

    • 一、前言
    • 二、常见的字符串拼接手段
    • 三、效率比较
    • 程序bug更改
      • stringstream使用str()转换成string的时候是否有效率问题
    • 结论、

一、前言

在C++中,我们有很多处理字符串的方式,本文讨论这个问题主要是在算法比赛中,在处理大规模字符串的时候,如何去降低程序的运行时间,因为在算法中程序运行时间是很宝贵的,但是在实际的工作中我们往往只需要实现功能即可。

二、常见的字符串拼接手段

由于博主C++只学到了C++11,因此这里只说我说了解到的C++11的内容,对于高版本C++不进行探讨。
我们常用的字符串拼接操作有如下几种:
1. string中重载了“+”,我们可以拿来直接用
2. string中提供了字符串拼接函数:append()
3. 使用C++标准库:stringstream

三、效率比较

这里我写了一段简单的程序:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

// n是字符串拼接次数
void sstreamAppend(int n){
    stringstream ss;
    ss.str("");
    int i = 0;
	string res = "";
		
    auto start = std::chrono::high_resolution_clock::now();
    while(i++ < n){
        ss << i;
        
    }
    res = ss.str();
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    cout << "stringstream拼接" << n << "次字符串所耗费时间为:" << duration.count() << "ms" << endl;
    // cout << "字符串拼接结果为:" << res << endl;
}

// 使用加法的
void stringAdd(int n){
    string res = "";
    int i = 0;
    auto start = std::chrono::high_resolution_clock::now();
    while(i++ < n){
        // res += to_string(i);
        res += i;
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    cout << "string使用“+”拼接" << n << "次字符串所耗费时间为:" << duration.count() << "ms" << endl;
    // cout << "字符串拼接结果为:" << res << endl;
}

// 使用函数std::string::append
void stringAppend(int n){
    string res = "";
    int i = 0;
    auto start = std::chrono::high_resolution_clock::now();
    while(i++ < n){
        res.append(to_string(i));
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    cout << "string使用append拼接" << n << "次字符串所耗费时间为:" << duration.count() << "ms" << endl;
    // cout << "字符串拼接结果为:" << res << endl;
}

int main(){
    int n;
    cout << "请输入需要进行拼接的次数" << endl;
    cin >> n;

    thread th1(sstreamAppend, n);
    th1.join();
    thread th2(stringAdd, n);
    th2.join();
    thread th3(stringAppend, n);
    th3.join();
}

我们需要认清楚这篇文章的定位:主要是针对算法比赛,而算法比赛中的字符串拼接通常比较简单,不涉及宽文本等内容,因此我将stringstream置于同等地位,我们需要知道,stringstream的优势是什么:

  1. 灵活
  2. 支持广泛:它可以支持宽字符等多种字符类型,而string不行,string只是基于ASCII码的

主要就是这两点吧。
==当我输入为一百万(1000000)的时候,我们可得到以下运行结果:C++字符串拼接的效率问题_第1张图片
可发现,此时的效率差距还是十分明显的,接下来我们就进行分析。

程序bug更改

先前的那段程序是有问题的,但是我一开始没注意到:我们应该都知道,string是基于ASCII码的,而中文部分使用的是ASCII码,这一点我在平时使用的时候就没怎么注意,因此上面犯了一个错误:我对一个string类型使用“+”,主要是加的是一个数字,而这个数字在字符串拼接的时候被认为是ASCII码,尽管我们没有使用“\”进行转义,但是编译器还是这么认为的,这是一个很低级的错误了。
而在使用append()的时候,这个函数对于参数是有要求的:==它要求参数是basic_string类型的,而我使用了函数to_string将int转换成了string类型,这才没有报错,因此我将有问题的地方进行了修改:C++字符串拼接的效率问题_第2张图片
修改后重新运行程序:
C++字符串拼接的效率问题_第3张图片
可以发现,使用“+”和append()的结果相差无几,但是由于使用了to_string函数,程序的运行效率大大降低,而stringstream仍然保持高效

stringstream使用str()转换成string的时候是否有效率问题

上面的代码我觉得还不够严谨:stringstream一直在进行流操作,而没有进行字符串的转换,因此为了结果的严谨,我在每次完成字符串拼接的时候,使用str()对字符流进行字符串提取:C++字符串拼接的效率问题_第4张图片
再次使用一百万(1000000)进行输入,等了很久都没有发现程序输出,于是将输入更改至一万(10000),可得如下结果:C++字符串拼接的效率问题_第5张图片
可发现stringstream具有严重的效率问题,而这个效率问题不在字符串拼接上,在于字符流的字符串提取操作中

结论、

如果只是大规模的字符串拼接,而在拼接过程中不需要频繁的使用,我更推荐使用stringstream;若是在拼接的过程中需要频繁使用未拼接完的字符串,更推荐使用string,而string的append和“+”没有明显的差异,更推荐append是因为“+”可能会忽视隐式转换,string的字符串拼接操作中,最影响效率的是to_string操作

你可能感兴趣的:(玩转C++,洛谷,c++,开发语言,算法)