Bug 23494 - std::basic_string <> capacity weirdness
Summary: std::basic_string <> capacity weirdness
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.2
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-20 16:22 UTC by Paul Pogonyshev
Modified: 2005-10-08 09:37 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Pogonyshev 2005-08-20 16:22:38 UTC
Whether capacity of strings shrinks depends on whether the strings are shared. 
I believe this also true for 4.0.1, but I only have the sources of it, didn't
compile.

To reproduce (note that `s2' is not shared at the time of push):

int
main()
{
  string s1;
  s1.reserve (10000);

  string s2 = s1;

  s1.push_back ('!');
  s2.push_back ('!');

  cout << "s1 capacity: " << s1.capacity () << endl;
  cout << "s2 capacity: " << s2.capacity () << endl;

  return 0;
}


Output (here):

s1 capacity: 1
s2 capacity: 12259
Comment 1 Andrew Pinski 2005-08-20 18:34:30 UTC
Why do you think this is a bug.  
Comment 2 Paul Pogonyshev 2005-08-20 18:48:53 UTC
Because it defeats the effect of reserve() call on `s1'.  I'm not saying I know
how to avoid it, but I wonder if there is some strict policy behind
`std::basic_string' reallocation behavior in GNU STL.  Maybe this example shows
that the policy is not implemented properly.

I think this example shows a perfectly common usage of strings where you reserve
space for all the things you are going to stuff in the string and then make a
copy of an intermediate results.  With current GNU STL behavior, this doesn't
work as expected, though, of course, it *will* give the correct result, it is
only about optimizations.
Comment 3 Paolo Carlini 2005-08-23 09:56:41 UTC
When push_back notices that s1 is shared and clones it (via reserve), creates
a new string (not shared) of capacity >= original size (according to an
exponential grow policy) but unrelated to the original capacity. I don't think
it would be wise to always take into account the original capacity, which can
be > size for *zillions* of different reasons, depending on the history of the
string, and not explicitly requested by the user via a previous reserve. Also 
notice that a *series* of push_back is typically very fast, because of the
exponential  reallocation policy and very often there is no real need for a 
reserve to obtain good performance. Also notice that some artifacts are
generally considered  unavoidable in a reference counted implementation of
string, as our default one (in mainline, we provide also an alternate
implementation in ext/vstring.h)
Comment 4 Paolo Carlini 2005-08-23 10:22:08 UTC
Of course, first copy-constructing s2, then calling s1.reserve also makes sense.
Comment 5 Paolo Carlini 2005-10-08 09:37:18 UTC
In fact, there isn't much more to say or do...