For example, I have two string objects:string str_1, str_2. I want to concatenate to them. I can use two methods: method 1:
std::stringstream ss;
//std::string str_1("hello");
//std::string str_2("world");
ss << "hello"<< "world";
const std::string dst_str = std::move(ss.str());
method 2:
std::string str_1("hello");
std::string str_2("world");
const std::string dst_str = str_1 + str_2;
Because the string's buffer is read only, when you change the string object, its buffer will destroy and create a new one to store new content. So method 1 is better than method 2? Is my understanding correct?
stringstreams
are complex objects compared to simple strings. Everythime you use method 1, a stringstream
must be constructed, and later destructed. If you do this millions of time, the overhead will be far from neglectible.
The apparently simple ss << str_1 << str_2
is in fact equivalent to std::operator<<(sst::operator<<(ss, str_1), str_2);
which is not optimized for in memory concatenation, but common to all the streams.
I've done a small benchmark :
in debug mode, method 2 is almost twice as fast as method1.
In optimized build (verifying in the assembler file that nothing was optimized away), it's more then 27 times faster.
Thans for everyone. Maybe I was a little lazy. Now I gave the code test.
test 1: 158.751ms, so long, my god!
int main()
{
chrono::high_resolution_clock::time_point begin_time = chrono::high_resolution_clock::now();
for(int i=0;i<100000;i++)
{
//string str_1("hello ");
//string str_2("world");
stringstream ss;
ss << "hello " << "world";
const string dst_str = ss.str();
}
chrono:: high_resolution_clock::time_point stop_time = chrono::high_resolution_clock::now();
chrono::duration<double> slapsed = duration_cast<duration<double>>(stop_time - begin_time);
cout << "time takes " << slapsed.count() * 1000 << "ms" << endl;
return 0;
}
test 2: 31.1946ms, fastest!
int main()
{
chrono::high_resolution_clock::time_point begin_time = chrono::high_resolution_clock::now();
for(int i=0;i<100000;i++)
{
string str_1("hello ");
string str_2("world");
const string dst_str = str_1 + str_2;
}
chrono:: high_resolution_clock::time_point stop_time = chrono::high_resolution_clock::now();
chrono::duration<double> slapsed = duration_cast<duration<double>>(stop_time - begin_time);
cout << "time takes " << slapsed.count() * 1000 << "ms" << endl;
return 0;
}
test 3: use boost::filesystem::path 35.1769ms, also a nice choice
int main()
{
chrono::high_resolution_clock::time_point begin_time = chrono::high_resolution_clock::now();
for(int i=0;i<100000;i++)
{
string str_1("hello ");
string str_2("world");
boost::filesystem::path dst_path(str_1);
dst_path += str_2;
const string dst = dst_path.string();
}
chrono::high_resolution_clock::time_point stop_time = chrono::high_resolution_clock::now();
chrono::duration<double> slapsed = duration_cast<duration<double>>(stop_time - begin_time);
cout << "time takes " << slapsed.count() * 1000 << "ms" << endl;
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With