通过默认复制构造函数比较 C++ 字符串是否会影响性能,原因为何?

Does comparing c++ strings via default copy constructor impact performance and why?

本文关键字:性能 影响 因为 是否 复制 默认 构造函数 比较 字符串 C++      更新时间:2023-10-16

我试图了解std::string复制构造函数用于字符串比较时的性能影响。这是我为测试编写的代码

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <sstream>
#include <algorithm>
#include <iterator>
void function1(std::string& v1)
{
std::string result;
std::string v2 = v1;
for(int i = 0; i<v1.size(); ++i)
{
if(v1[i] == v2[i])
{
result="function1: Elements are the same for " + std::to_string(i) + " times";
}
}
std::cout<<result<<'n';
}
void function2(std::string& v1)
{
std::string result;
std::string v2 = v1;
for(int i = 0; i < v1.size(); ++i)
{
if(std::string(v1[i],1) == std::string(v2[i],1))
{
result="function2: Elements are the same for " + std::to_string(i) + " times";
}
}
std::cout<<result<<'n';
}
int main()
{
using namespace std;
string longString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Vestibulum at velit in erat hendrerit venenatis at nec lorem. Etiam ante justo, "
"finibus vel erat ut, porttitor vestibulum diam. Aenean a mauris id ante porta pulvinar. "
"Mauris est est, lacinia a placerat ut, eleifend quis nisl. Ut posuere ultrices interdum. "
"Morbi tristique elit quis nibh pharetra, vel aliquam libero iaculis. Suspendisse tempus,"
"orci non volutpat hendrerit, metus ex feugiat risus, id vehicula risus velit eu elit. "
"Mauris iaculis vehicula turpis, vitae tempor leo elementum id. Maecenas rhoncus ex quis" 
"nulla tincidunt consectetur. Sed sit amet lectus tempor, egestas libero quis, viverra massa. C++";
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
function1(longString);
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;
std::cout << "------------------    " << std::endl;
begin = std::chrono::steady_clock::now();
function2(longString);
end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;
}

在我的本地机器上,我得到以下结果:

function1: Elements are the same for 670 times
Time difference = 395[µs]
Time difference = 395565[ns]
------------------    
function2: Elements are the same for 670 times
Time difference = 475[µs]
Time difference = 475549[ns]

为什么会有时差?std::string复制构造函数是否会导致这种性能差异,为什么?

在 function2 中,每次想要比较元素时都会构建新字符串,这很昂贵。

在这种情况下,另一种选择可能是使用string_view,您可以在此处看到修改,但它仍然矫枉过正,因为您只想比较两个对象。在这种情况下,不需要中间对象。

我知道您可能正在尝试一些事情,但是使用"=="运算符直接比较两个字符串更简单。它更清晰,更快。有关该方法与前两个函数的比较,请参阅此处。

在第一个函数中,您将字符与字符进行比较,这非常便宜

但是在第二个中,您每次迭代都用一个字符构造两个字符串,然后比较它们并在迭代结束时被破坏,但是,性能没有太大差异,因为由于 SSO 优化,此分配不会分配内存,编译器可以在编译时推断字符串长度,但它不能使其像第一个函数那样具有性能