Since I’ve started using Qt, I loved the “implicit sharing” concept it uses for it’s strings and container types. It become so much easier to pass these data around. I wasn’t aware that some STL implementations have copy-on-write semantics for strings as well. When I saw some recommendations for std::string on Stack Overflow, I’ve decided to check out the implementation in GCC and discovered that it indeed does some reference counting.
So the next step was comparing the implementations. I wrote a little program today to check how QString and std::wstring compare in terms of copy-on-write performance. Since QChar is 2 bytes and wchar_t is 4 bytes on my machine, it wouldn’t be completely fair comparison, so I’ve included also std::string. The results were quite surprising for me. STL does almost always better, but for some reason I wasn’t able to make not dereference the string on read-only operations.
| wchar_t* | QString | std::wstring | std::string | |
|---|---|---|---|---|
| Read | 0 ms | 0 ms | 2143 ms | 2224 ms |
| Write | 0 ms | 5588 ms | 2621 ms | 2570 ms |
| Copy | 1618 ms | 601 ms | 116 ms | 117 ms |
| Copy + read | - | 601 ms | 6161 ms | 5079 ms |
| Copy + write | - | 11036 ms | 6822 ms | 6843 ms |
| Copy + append | - | 5801 ms | 4650 ms | 3482 ms |
The table shows times in milliseconds for 10000000 repeated operations on a 200-character long string.
- “Read” just reads the string one character at a time, using the default
[]operator. I’ve tried hard to find a cheaper way to do this for STL strings, but I failed (I wasn’t interested in usings.data()and then working with the primitive array, I wanted to work with the object directly). - “Write” writes to all characters of the string, again one character at a time.
- “Copy” assigns one string to another, using the default
=operator for string classes andmemcpyforwchar_t*. - “Copy + read” is the same as “Copy“, followed by “Read” performed on the copy.
- “Copy + write” is the same as “Copy“, followed by “Write” performed on the copy.
- “Copy + append” is again the same as “Copy“, followed by appending a short string to the copy.
I guess I should note that this wasn’t meant to be a generic benchmark of the string classes. I just wanted to know performance details about the copy-on-write implementations in them. The conclusion for me is that the STL strings in GCC are better than I always thought, but the fact that they dereference the data on read-only operations is not very nice.

