11

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?

17
  • 2
    The answer is obvious (i.e., method #2). You avoid the creation of a stringstream plus the two insertions plus the call to .str(). Commented May 15, 2015 at 7:45
  • 4
    @cwfighter Did you try to profile the two options? Commented May 15, 2015 at 7:50
  • 3
    C++ != C# or Java. C++ strings are not immutable. Commented May 15, 2015 at 7:58
  • 4
    Can you define "better"? Commented May 15, 2015 at 8:07
  • 1
    @cwfighter Why don't you consider aspects such as readibility, error checking? Commented May 15, 2015 at 8:17

3 Answers 3

11

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for yous help. My test is same as your answer.
@DawidDrozd Because the narrative explains why it will be faster in any situation. The difference in debug shows only the effect effect that corresponds to the explanation, whereas the optimized version adds other improvements on top.
2

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;
   }

Comments

1
  • Method 2 is better as your situation here. Since it has better readability and time cost less for declining the stringstream obj creation.
  • But, I strongly recommend to use format for better readability & maintenance, instead of "+" or other string concatenation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.