Difference between std :: string (size, '\ 0') and s.resize (size)?

Unlike std :: vector, std :: string does not provide a unary constructor that takes size:

std::string s(size); // ERROR 

Is there a difference between:

 std::string s(size, '\0'); 

and

 std::string s; s.resize(size); 

in terms of their performance with common implementations?

Will resizing initialize the string to all null characters or will it leave them an undefined value?

If all is zero, is there a way to build a string of a given size, but leave characters with an undefined value?

+7
c ++ c ++ 14
source share
4 answers

There is a difference, as in std::string s(size, '\0'); , all memory needed for a string can be allocated immediately. However, with the second example, if size larger than the number of characters stored to optimize small lines, you may need to perform additional distribution, although this implementation is defined and definitely will not be more effective in this regard in the standard C ++ 17 implementation. However, the first example more consensus and may be more effective, so it is probably preferable. When calling s.resize(size); all new characters will be initialized by the default constructor char , aka '\0' . Unable to initialize string with undefined values.

+4
source share

The actual answer will be implementation based, but I'm sure std::string s(size, '\0'); works faster.

 std::string s; s.resize(size); 

According to the documentation for std :: string .

1) The default constructor. Creates an empty string (zero size and unspecified capacity).

The default constructor will create a string with "undefined capacity". I mean, the implementation can freely determine the default capacity, possibly in the range of 10-15 characters (full speculation).

Then, on the next line, you reallocate the memory ( resize ) with the new size , if size greater than the current capacity . This is probably not what you want!

If you really want to find out finally, you can start the profiler in two ways.

+4
source share

There is already a good answer from DeepCoder .

However, for records, I would like to point out that strings (as for vectors) have two different concepts:

  • size() : this is the number of actual (i.e. significant) characters in the string. You can change it using resize() (to which you can provide a second parameter to say that you want to use char as a filler if it should be other than '\0' )
  • capacity() : this is the number of characters allocated to the string. Its at least size, but may be larger. You can increase it with reserve()

If you are worried about distribution performance, I find it better to play with capacity. The size should really be saved for real characters in a string, not to fill characters.

By the way, in the general case, s.resize(n) same as s.resize(n, char()) . Therefore, if you want to fill it in the same way when building, you can consider string s(n, char()) . But until you use basic_string<T> to make T different from characters, your '\ 0' just does the trick.

+2
source share

Resizing does not leave items uninitialized. According to the documentation: http://en.cppreference.com/w/cpp/string/basic_string/resize

s.resize(size) will initialize the value of each added character. This will initialize each element of the modified row to '\0' .

You will need to measure the performance difference of your specific C ++ implementation to really decide if there is a price difference or not.

Looking at the machine generated by Visual C ++ for optimized builds, I can say that the amount of code for any version is similar. What seems like an intuitive counter is that the resize () version is being measured faster for me. However, you should check out your own compiler and standard library.

+1
source share

All Articles