1

Can the std::string capacity be changed to optimise it?

For example:

std::string name0 = "ABCDEABCDEABCDEF"; int cap = name0.capacity(); //cap = 31 int size = name0.size(); //size = 16 

Okay, this is perfectly fine for a couple of strings in memory, but what if there are thousands? This wastes a lot of memory. Isn't it then better to use char* so you can control how much memory is allocated for the specific string?

(I know some people will ask why are there thousands of strings in memory, but I would like to stick to my question of asking if the string capacity can be optimised?)

5
  • 1
    A string will reserve more space than is being used, this is because its very expensive to reallocate memory. if you know the size of input strings then it may be useful to use char* but if you don't std::string's are still preferable. Commented May 29, 2014 at 14:07
  • With C++11 there's the method shrink_to_fit(): en.cppreference.com/w/cpp/string/basic_string/shrink_to_fit Commented May 29, 2014 at 14:07
  • "but what if there are thousands? This wastes a lot of memory." I don't think so. Let's say every string has 20 characters, and you have 10000 strings. That's about 200000 bytes. About 195 KB. That's almost nothing by today's standards, except perhaps in very special environments. Commented May 29, 2014 at 15:04
  • Are you sure you actually need to do this optimization? Have you actually ran into a situation where using the extra memory causes a problem? Making the code more complicated is likely to cause you more problems in the long run than is using the extra memory. The maintenance costs are non-trivial. Commented May 29, 2014 at 15:33
  • You might want to determine whether your string is using the small string optimization and what the internal size is. On 64 bit systems I think it is likely to use a 31 char footprint. You won't get the footprint reduced below that size. Commented May 29, 2014 at 15:38

1 Answer 1

4

If you're asking how to reduce capacity() so that it matches size(), then C++11 added shrink_to_fit() for this purpose, but be aware that it is a non-binding request, so implementations are allowed to ignore it.

name0.shrink_to_fit(); 

Or there's the trick of creating a temporary string and swapping:

std::string(name0.begin(), name0.end()).swap(name0); 

However, neither of these are guaranteed to give you a capacity() that matches size(). From GotW #54:

Some implementations may choose to round up the capacity slightly to their next larger internal "chunk size," with the result that the capacity actually ends up being slightly larger than the size.

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

4 Comments

Yes, as you said neither of these give a capacity that matches size. They end up with exactly the same capacity.
@worker11811 Are you using MSVC? IIRC, it uses a 16-byte fixed buffer for small string optimization, and your string is 16-bytes, which leaves no room for a null character. It is possible the implementation starts out with a 32-byte capacity as soon as it is forced to do dynamic allocation. In any case, I don't know of any portable, guaranteed way of getting what you want.
Yes, I am using MSVC. I guess the question is a bit more philosophical. I am bench marking for different solutions and noticed that the std::string solution almost doubles memory when doing it with a 16 character string. This was for the worst case scenario and the result wasn't very good. I know that using strings has other advantages, but this is a concern when looking at memory usage.
Dynamic allocation has a certain granularity in reality; any good implementation will probably round the needed size up to this granularity, since that's the amount of memory that it will get anyway.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.