Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is stringstream better than string's operator '+' for string objects concatenation?

Tags:

c++

string

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?

like image 700
cwfighter Avatar asked May 15 '15 07:05

cwfighter


2 Answers

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.

like image 137
Christophe Avatar answered Nov 10 '22 02:11

Christophe


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;
   }
like image 40
cwfighter Avatar answered Nov 10 '22 02:11

cwfighter