To std::string or not to std::string...

Hello,

I am a little confused over why exactly c++ library strings (std::string) are faster in this example I ran across:

Taken from C++ primer 4e (Lippman, et al)*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//C-style character string implementation
const char *pc = "a very long literal string";
const size_t len = strlen(pc + 1); //space to allocate
//performace test on string allocation and copy
for(size_t ix = 0; ix !=1000000; ++ix)
{
     char *pc2 = new char[len + 1];  //allocate the space
     strcpy(pc2, pc);        //do the copy
     if(strcmp(pc2, pc))     //use the new string
          ;                  //do nothing
     delete [] pc2;
}

//string implementation
string str("a very long literal string");
//performance test on string allocation and copy
for(int ix = 0; ix !=1000000; ++ix)
{
     string str2 = str;     //do the copy, automatically allocated
     if(str != str2)        //use the new string
          ;                 //do nothing
}


*Program is for illustrative purposes.

I get that c++ library strings are easy to implement, less error prone, etc. But I would figure that in some cases the raw implementation of c-style strings would outperform their library counterparts. Are their cases where c-style is preferred? Some insight would be appreciated.

Thanks. cppdna
many developers have spent many hours fine tuning std::string for speed and efficiency. On large scale operations like the above, your code is unlikely to beat it.

Old style C char arrays are only likely to be better for simpler operations, where using a std::string would be equivalent to a sledge hammer to crack a nut, or the cost of instantiating a std::string is not worth it just to copy a couple of chars around.

Hope this helps
I believed std::string to definitely be more efficient in terms of code length, but I thought that this came at a cost. I thought for something as basic as allocation and copying there wouldn't be such a significant improvement. But in fact on my computer the difference is almost 3 fold in favor of std::string!

I do like the sledge hammer anaolgy. ;p
A slege hammer would work through a slab of concrete in no time, but a regular hammer would take forever!
I wonder if the analogy would still hold up in the case of many tiny nuts; a sledge hammer would take care of it but it would be harder to move around and get going, whileas the smaller hammer would be easier to manipulate and be better suited for the task...
[apologies ahead of time if that didn't make sense :p]

Thanks again.
Hi,

I on my machine, the C-Style one is about twice as fast. I also noticed that you have an error in this line

const size_t len = strlen(pc + 1); //space to allocate

should be;

const size_t len = strlen(pc); //space to allocate

since you are already adding 1 to len inside the loop

Dan
Last edited on
Yeah, I got this example from a book. I noticed the same thing: they effectively add an extra space for the null twice. Good catch though. ;)

They don't list the problem under their errata on their website.

I am surprised that your C-Style string allocation was faster...why would that be?

There are many implementations of the std library just like there are many compilers. The only requirements for it to be std library compatible really are the methods available and the behaviours under specified conditions. I should point out that these specifications are extensive, not just a couple of pages. Beyond that it is down to the person writing the code.

The variations in speed between the std library and C style operations are wholly dependent on which library you are using (who wrote it), which compiler you are using and which platform you are running on.

My comment above still holds true in general but there will always be combinations of library and compiler that prove to be an exception.

Bertha
some implementations may allocate a fixed (stacked) initial buffer and only use the heap if more memory is needed

the implementation you used may be avoiding the whole new and delete process, or may be using a memory pool (which also avoids new and delete for almost all constructions and destructions)
Many string implementations use copy-on-write semantics.

In your example,

 
string str2 = str;


is equivalent to

 
string str2( str );


ie, it runs string's copy constructor which, rather than copying the whole "char array", just copies a pointer to the array. The deep copy is made only when one of the two strings is written to. Thus, in your example, the C version copies far more bytes than the C++ /std::string version, and this is why you see the performance improvement.
Topic archived. No new replies allowed.