 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Erik Guest
|
Posted: Wed Aug 03, 2005 10:08 am Post subject: surprising std::string behaviour |
|
|
Hello,
I was a little bit surprised when I tested the string members resize
and reserve.
I thought that:
- reserve only change the capacity, if the paramater is higher or equal
than the actual capacity. It never should reduce the capacity.
- reserve increase the capacity exactly to the given size.
- resize changes the capacity and the size (I read that in some C++
Books, but I think I should throw them away)
but the results delivers:
- resize do not change the capacity of a string. Thus you cannot reduce
the memory
already allocated by a string.
- reserve is able to decrease the capacity of a string (borland, VC++)
- reserve allocates the required memory or even more
- resize do not change the capacity of a string (only the size)
- the initial capacity of a string depends on the used compiler
Is each compiler comform to the C++ Standard?
Is it possible to reduce the capacity of a string?
//-------------------------------------------------------------------------------
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
void print_header()
{
cout << "+------+----------+" << endl
<< "| " << "size" << " | " << "capacity" << " |"
<< endl;
}
void print_data(string & s)
{
cout << "|------+----------|" << endl
<< '|'
<< setw(5) << s.length() << " |"
<< setw(9) << s.capacity() << " |"
<< endl;
}
int main()
{
print_header();
string s1;
print_data(s1);
s1.reserve(20);
print_data(s1);
s1.resize(5);
print_data(s1);
s1.reserve(10);
print_data(s1);
s1.reserve(1000);
print_data(s1);
s1.resize(1);
print_data(s1);
}
Let's see the output different compilers produced.
//--output gcc-----------------
+------+----------+
| Quote: | size | capacity |
------+----------|
0 | 0 |
------+----------|
0 | 20 |
------+----------|
5 | 20 |
------+----------|
5 | 20 |
------+----------|
5 | 1123 |
------+----------|
1 | 1123 |
|
//--output VC++-----------------
+------+----------+
| Quote: | size | capacity |
------+----------|
0 | 15 |
------+----------|
0 | 31 |
------+----------|
5 | 31 |
------+----------|
5 | 15 |
------+----------|
5 | 1007 |
------+----------|
1 | 1007 |
|
//--output Borland C++ Builder 6 -----------------
+------+----------+
| Quote: | size | capacity |
------+----------|
0 | 7 |
------+----------|
0 | 20 |
------+----------|
5 | 20 |
------+----------|
5 | 10 |
------+----------|
5 | 1000 |
------+----------|
1 | 1000 |
|
//--------------------------------------------------
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Wed Aug 03, 2005 1:06 pm Post subject: Re: surprising std::string behaviour |
|
|
"Erik" <erik.griessmann (AT) fmc-ag (DOT) com> skrev i meddelandet
news:1123050764.832100.325480 (AT) f14g2000cwb (DOT) googlegroups.com...
| Quote: | Hello,
I was a little bit surprised when I tested the string members resize
and reserve.
I thought that:
- reserve only change the capacity, if the paramater is higher or
equal
than the actual capacity. It never should reduce the capacity.
- reserve increase the capacity exactly to the given size.
- resize changes the capacity and the size (I read that in some C++
Books, but I think I should throw them away)
but the results delivers:
- resize do not change the capacity of a string. Thus you cannot
reduce
the memory
already allocated by a string.
|
resize changes the size of the string. It does not decrease the
capacity, but might have to increase it.
| Quote: | - reserve is able to decrease the capacity of a string (borland, VC++)
|
A note in the standard says:
"Calling reserve() with a res_arg argument less than capacity() is in
effect a non-binding shrink request. A call with res_arg <= size() is in
effect a non-binding shrink-to-fit request."
So, reserve is allowed but not required to shrink the capacity. If it
generally doesn't, you should talk to you compiler supplier.
| Quote: | - reserve allocates the required memory or even more
|
Yes, it might not be possible or "efficient" to allocate the exact size
you requested.
For example, reserve(37) might not be able to allocate exactly 37
characters, because the memory manager might not support that. Possibly
48, or 64, characters might be what is available. The capacity() could
then reflect that number, and not be 37.
| Quote: | - resize do not change the capacity of a string (only the size)
|
It might increase the capacity, if necessary.
| Quote: | - the initial capacity of a string depends on the used compiler
|
Yes.
The default constructed string
std::string s;
has size()==0 and capacity() is "an unspecified value". (Table 38 in
the standard).
The capacity of 15 you see for one implementation is an effect of the
"small string optimization" used. As long as the string is within that
size, it is kept inside the string object. Only if it is larger, does
the string have to allocate dynamic memory for it.
| Quote: |
Is each compiler comform to the C++ Standard?
|
It seems so to me.
| Quote: | Is it possible to reduce the capacity of a string?
|
You can ask for a reduction using reserve(). You cannot force it.
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Daughtry Guest
|
Posted: Wed Aug 03, 2005 2:24 pm Post subject: Re: surprising std::string behaviour |
|
|
| Quote: | I was a little bit surprised when I tested the string members resize and reserve.
That's because you had unwarranted misconceptions about how they should |
work.
| Quote: | resize do not change the capacity of a string
That's conforming, and a reasonable expectation since having the string |
allocating memory, then releasing it only to likely allocate it again
shortly after is silly.
| Quote: | reserve is able to decrease the capacity of a string (borland, VC++)
That's conforming, and also expected behavior. |
| Quote: | resize do not change the capacity of a string (only the size)
If the new size of the string fits within the capacity, there's no |
point in changing it. If, however, the new size is greater than the
capacity and less than or equal to max_size() then the only way yo
satisfy the call is to change the capacity.
| Quote: | the initial capacity of a string depends on the used compiler
Once again, conforming. The standard doesn't dictate minute details |
like this.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Wed Aug 03, 2005 2:26 pm Post subject: Re: surprising std::string behaviour |
|
|
* Bo Persson:
| Quote: | * Erik Griessmann:
Is it possible to reduce the capacity of a string?
You can ask for a reduction using reserve(). You cannot force it.
|
int main()
{
std::string largum = "hello, cruel world";
largum.reserve( 4096 );
std::cout << largum.capacity() << std::endl;
// Reduce that capacity with granularity of implementation.
{
std::string smallum = largum;
largum.swap( smallum );
}
std::cout << largum.capacity() << std::endl;
}
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Erik Guest
|
Posted: Thu Aug 04, 2005 10:39 am Post subject: Re: surprising std::string behaviour |
|
|
Hi James,
Thanks for your competent explanations. I think I have now a better
understanding for this subject.
| Quote: | That's because you had unwarranted misconceptions about how they should
work.
You are right. The unwarranted misconceptions derived from a C++-book |
called "C++ STL" from the author Anderé Willms. I will throw away this
book and use better ones.
Regards,
Erik
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Aug 04, 2005 10:44 am Post subject: Re: surprising std::string behaviour |
|
|
Bo Persson wrote:
| Quote: | "Erik" <erik.griessmann (AT) fmc-ag (DOT) com> skrev i meddelandet
news:1123050764.832100.325480 (AT) f14g2000cwb (DOT) googlegroups.com...
|
[...]
| Quote: | - reserve is able to decrease the capacity of a string
(borland, VC++)
A note in the standard says:
"Calling reserve() with a res_arg argument less than capacity() is in
effect a non-binding shrink request. A call with res_arg <= size() is in
effect a non-binding shrink-to-fit request."
So, reserve is allowed but not required to shrink the
capacity. If it generally doesn't, you should talk to you
compiler supplier.
|
That's interesting. Does anyone know why this is different for
string than for the other containers (e.g. vector)? It seems
more than a little inconsistent.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Erik Guest
|
Posted: Thu Aug 04, 2005 12:34 pm Post subject: Re: surprising std::string behaviour |
|
|
I think there is a little bug in your code.
Please take a look at my toy code I compiled using gcc.
It seemed that the operator= and the copy constructor is allowed to
overtake the capacity of its string parameter. When I used the
constructor using iterators the swap trick is working.
//----------------------------------------------------
#include <iostream>
#include <string>
using namespace std;
string & reduce_capacity(string & str)
{
string reducer(str.begin(),str.end());
str.swap(reducer);
return str;
}
string & no_reduce_of_capacity(string & str)
{
//copy constructor do not match requirement
//to reduce capacity
string reducer(str);
str.swap(reducer);
return str;
}
void out(string & s)
{
cout << "value : " << s << endl
<< "lenght: " << s.length() << endl
<< "capacity: " << s.capacity() << endl;
}
int main()
{
string s("I wanna grow");
out(s);
s.reserve(1000);
out(s);
out(no_reduce_of_capacity(s));
out(reduce_capacity(s));
}
//----------------------------------------------------
// output -----------------------------------------
value : I wanna grow
lenght: 12
capacity: 12
value : I wanna grow
lenght: 12
capacity: 1123
value : I wanna grow
lenght: 12
capacity: 1123
value : I wanna grow
lenght: 12
capacity: 12
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 05, 2005 3:06 pm Post subject: Re: surprising std::string behaviour |
|
|
Alf P. Steinbach wrote:
| Quote: | * Bo Persson:
* Erik Griessmann:
Is it possible to reduce the capacity of a string?
You can ask for a reduction using reserve(). You cannot force it.
int main()
{
std::string largum = "hello, cruel world";
largum.reserve( 4096 );
std::cout << largum.capacity() << std::endl;
// Reduce that capacity with granularity of implementation.
{
std::string smallum = largum;
largum.swap( smallum );
}
std::cout << largum.capacity() << std::endl;
}
|
What makes you thinkg that this will work? It doesn't work with
any of the implementations available to me (g++, Sun CC), and
the standard certainly doesn't say anything about it.
As far as I know, there is no way to ensure a minimum
capacity(). For any container, for that matter. Typically,
however, I would expect the swap idiom above to work for
constructors requiring a deep copy -- which means the copy
constructor for all containers except std::string. For most
current implementations of std::string, using the two iterator
constructor would suffice, although I can conceive of
implementations where it wouldn't. (An implementation optimized
for substr() in a single threaded environment, or with garbage
collection, for example.) Probably even surer would be:
std::string smallum( largum.data(), largum.size() ) ;
It would take a fairly perverse implementation to test that the
char const* actually pointed to an existing shared
representation, find the shared representation, and use its
capacity.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sat Aug 06, 2005 11:16 am Post subject: Re: surprising std::string behaviour |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: |
That's interesting. Does anyone know why this is different for
string than for the other containers (e.g. vector)? It seems
more than a little inconsistent.
|
Probably a historical artifact. They were developed independently, and
the STL interface was forced onto basic_string hastily.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Sun Aug 07, 2005 1:37 am Post subject: Re: surprising std::string behaviour |
|
|
* [email]kanze (AT) gabi-soft (DOT) fr[/email]:
| Quote: | Alf P. Steinbach wrote:
* Bo Persson:
* Erik Griessmann:
Is it possible to reduce the capacity of a string?
You can ask for a reduction using reserve(). You cannot force it.
int main()
{
std::string largum = "hello, cruel world";
largum.reserve( 4096 );
std::cout << largum.capacity() << std::endl;
// Reduce that capacity with granularity of implementation.
{
std::string smallum = largum;
largum.swap( smallum );
}
std::cout << largum.capacity() << std::endl;
}
What makes you thinkg that this will work?
|
See Erik's follow-up to the same posting.
Using the copy constructor is a lazy-bug.
It's a bug, and it's there because I'm naturally lazy, but happily Erik (the
OP) got the idea in spite of that bug -- problem solved.
| Quote: | It doesn't work with
any of the implementations available to me (g++, Sun CC),
|
Works fine with MSVC.
| Quote: | and the standard certainly doesn't say anything about it.
As far as I know, there is no way to ensure a minimum
capacity(). For any container, for that matter.
|
See above.
There is, at least if you don't insist on an absolute "minimum". ;-)
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|