4

The following piece of code:

string a = "abc";
cout << a.capacity();
a.erase(a.begin() + 1, a.end());
cout << a.capacity();

...outputs:

33

Even if I remove some elements from the string, the capacity remains the same. So my questions are:

  1. Is some memory being held up because of capacity? What if I have not explicitly reserve()'d?

  2. If I use reserve() and don't end up using the entire capacity, am I wasting memory?

  3. Will this extra memory (which I am not using) be allocated to something else if required?

EDIT: Suppose i have

 string a= "something";
 a = "ab";

Now I know that a won't ever have more than two characters. So is it wise to call reserve(2) so that memory is not wasted?

m8mble
  • 1,283
  • 1
  • 15
  • 26
Gaurav Sehgal
  • 7,011
  • 2
  • 15
  • 29
  • What does the "edited" part mean: What do you mean by "know that `a` won't have more than two characters"? Which `size` does `a` have at this point? If you didn't change `a` by then, `a` has more than two characters. – m8mble Jan 03 '17 at 10:29
  • @m8mble I mean i will remove some characters from `a` and i know i won't be putting more characters into it. – Gaurav Sehgal Jan 03 '17 at 12:20
  • I've added a section explicitly for this added question. – m8mble Jan 03 '17 at 12:24

2 Answers2

6

I'll answer your questions first:

  1. The memory belongs to the string, but isn't used entirely. If you don't reserve, you can't control the capacity. You just know it is sufficiently large.

  2. Correct.

  3. As said in 1): no. It belongs to the string. Nothing else can use this memory. The string itself could use it for additional characters though.

For further details I'd recommend the documentation of string::reserve.

One final remark: If you don't ever reserve, everything will work fine - it might be unnecessarily slow though. That is only ever the case if you were to frequently add few characters and the string has to re-alloc alot (much like a vector). Reserving is basically intended to bypass this situation.


On the addendum: Calling reserve can help to save memory. If you call reserve(n), this ensures the string has an internal capacity for at least n characters. Note that reserve is not required to set the capacity to exactly n nor to reduce the capacity at all for small n (cf. reserve documentation).

Back to your example: If you call reserve it can never do any harm. It's the best you can do in general. (In case you have C++11 features, I'd recommend shrink_to_fit).

I tested with (older) versions of gcc / clang in which cases the capacity of a got changed to exactly 2. Since I'm not 100% sure what the added question referes to, here is what I ran:

auto a = string{"something"};
a = "ab";
cout << a << " " << a.capacity() << endl;
a.reserve(2);
cout << a << " " << a.capacity() << endl;

Which produces:

ab 9
ab 2
m8mble
  • 1,283
  • 1
  • 15
  • 26
  • 2
    +1. It may be worth mentioning that [`shrink_to_fit`](http://en.cppreference.com/w/cpp/string/basic_string/shrink_to_fit) can be used to try and free up some of the memory. – jogojapan Jan 03 '17 at 09:08
  • 3
    @m8mble: I think in the year 2017 one can assume that - unless specified otherwise - questions tagged with c++ refer (knowingly or unknowingly) to at least c++11 (somewhat dangerous assumption for MSVC++ users). – MikeMB Jan 03 '17 at 09:35
  • 1
    ... and it's non-binding. @jogojapan – Lightness Races in Orbit Jan 03 '17 at 09:45
  • 1
    @MikeMB: Mmmmm nope! – Lightness Races in Orbit Jan 03 '17 at 09:45
  • @Lightness: Why not? I'm not saying everyone can use a c++11 compiler (I often can't) but imho it is a reasonable default assumption. – MikeMB Jan 03 '17 at 09:52
  • @Lightness: Out of curiosity (not directly related to the answer): Have you encountered situations, where shrink to fit didn't work but alternatives like swap did? – MikeMB Jan 03 '17 at 09:54
  • @MikeMB: Meh okay I suppose. – Lightness Races in Orbit Jan 03 '17 at 09:54
  • @MikeMB: I don't think I've ever checked either way. Never needed to shrink to fit. But I don't think I'd expect one to "work" but not the other. – Lightness Races in Orbit Jan 03 '17 at 09:55
  • 1
    @MikeMB C++11 is not widespread. Although modern compilers support it, many people don't use modern compilers (I don't), and that is not always by choice. If a question is tagged `c++`, don't assume C++11 or later, there are other tags for those versions. – Remy Lebeau Jan 03 '17 at 09:59
  • 1
    @RemyLebeau: There are also separate tags for c++03 and c++98. As I said, I'm also not always able to use a c++11 compiler but if that is the case, I mention that constraint explicitly. Just like mentioning if my program has to compile with Visual studio or has to run on a microcontroller. I'm not saying you shouldn't mention that part of your answer relies on c++11, but restricting your answer to the c++03 feature set unless the OP explicitly asks for a c++11 solution imho reduces it's value. I'd like to add that `shrink_to_fit` was available even before c++11 got standardized. – MikeMB Jan 03 '17 at 10:55
-1

1) Is some memory being held up because of capacity? What if i have not explicitly reserve()'d?

Even if you did not call reserve, the std::string object can still hold up some memory1 for (even a default constructed) std::string. And this is true with std::string implementations that uses Short String Optimization

2)If i use std::reserve() and dont end up using the entire capcity then am i wasting memory?

It depends on what you mean by wasting memory; std::string dynamically resizes its buffer to accommodate changes in the size of the string. Well, in the case of Short String Optimized std::string implementations, there is nothing you can do about it. The memory is in the string object itself.

3)Will this extra memory which i am not using be allocated to something else, if required?

No. A std::string object manages the memory it allocated, and it may or may not give it up2 wholly or partly, until its destroyed. See David Schwartz's comment

EDIT: Suppose i have

string a= "something";

Now i edit the string and know that a won't have more than two characters.So is it wise to call a.reserve(2) so that memory is not wasted?

If you modified a in a way that changes a.size(), such as calling resize method or assigning it to a new string of length 2, then the proceeding reserve call can2 be beneficial.

Note that, calling reserve would not reduce the string's contents. std::string::reserve is not permitted to truncate the string. It is only permitted to work on unused memory. If you call std::string::reserve(new_capacity_intended) with new_capacity_intended less than the size() of the string, the best that could possibly happen is the same effect of std::string::shrink_to_fit.

To reduce the string's memory (if the implementation does a binding shrink_to_fit request) and shrink it to the first two characters:

string a= "something";
//resize it first
a.resize(2);  //or by some assignment such as a = "so";

//then
a.reserve(2); // or better still a.shrink_to_fit();

1: by memory, I assume Virtual Memory

2: std::string::reserve or std::string::shrink_to_fit may or may not give up the string's unused memory.

Community
  • 1
  • 1
WhiZTiM
  • 19,970
  • 3
  • 36
  • 56
  • Suppose i have `string a= "something";`Now i edit the string and know that `a` won't have more than two characters.So is it wise to call `reserve(2)` so that memory is not wasted? – Gaurav Sehgal Jan 03 '17 at 09:21
  • Per OP comments he doesn't call reserve "with a capacity less than the `size()` of the string". That seems misleading.... – m8mble Jan 03 '17 at 12:52
  • @WhiZTiM Assuming by "memory" he means RAM, your answer to 3 is wrong in general. For example, if the string is large enough to include several pages of memory, the OS can swap out the string's contents and use the RAM for something else. (That's just one example, there are other ways the memory could be reused.) It's probably right for his specific code example. – David Schwartz Jan 03 '17 at 13:33
  • @DavidSchwartz, thats true.. though by "memory", I simply presumed "Virtual Memory". I've updated my answer to capture that. – WhiZTiM Jan 03 '17 at 14:00
  • By the (yet again) edited OP, he doesn't "call `std::string::reserve(new_capacity_intended)` with `new_capacity_intended` less than the `size()` of the string". This part of the answer still is misleading... – m8mble Jan 03 '17 at 14:05
  • @m8mble, But the phrase you quoted was preceded by "If you" ... Making it *"If you call `std::string::reserve(new_capacity_intended)` with `new_capacity_intended` less than the size()..."* – WhiZTiM Jan 03 '17 at 14:22
  • @WhiZTiM I'm totally aware of this. I'm not saying you are wrong; I'm just pointing out that OP never intended to do this. In case someone is not aware of this, it will be confusing how this relates to the actual question. – m8mble Jan 03 '17 at 14:26