This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[v3] basic_string::reserve() shrink-to-fit?
- From: Neil Ferguson <nferguso at eso dot org>
- To: LibStdC++ General List <libstdc++ at gcc dot gnu dot org>
- Date: Thu, 11 Dec 2003 15:51:36 +0100
- Subject: [v3] basic_string::reserve() shrink-to-fit?
Hi, all -
I just tried the following bit of code on GCC 3.3, and the libstdc++
that comes with it:
--
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
cout << endl;
cout << "Version of libstdc++: " << __GLIBCPP__ << endl;
cout << endl;
cout << "Initial capacity: " << str.capacity() << endl;
str = "Wibble";
cout << "After 6 char assign: " << str.capacity() << endl;
str.reserve(1000000);
cout << "After reserve(1000000): " << str.capacity() << endl;
str.reserve();
cout << "After reserve(): " << str.capacity() << endl;
cout << endl;
}
--
and got this output:
--
Version of libstdc++: 20030513
Initial capacity: 0
After 6 char assign: 6
After reserve(1000000): 1003491
After reserve(): 1003491
--
ie. reserve() doesn't seem to shrink the string capacity to fit. On
examining basic_string::reserve() in basic_string.tcc:
--
template<typename _CharT, typename _Traits, typename _Alloc>
void
basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
{
if (__res > this->capacity() || _M_rep()->_M_is_shared())
{
if (__res > this->max_size())
__throw_length_error("basic_string::reserve");
// Make sure we don't shrink below the current size
if (__res < this->size())
__res = this->size();
allocator_type __a = get_allocator();
_CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
_M_rep()->_M_dispose(__a);
_M_data(__tmp);
}
}
--
the only way I can see for a shrink-to-fit to occur is if more than one
string refers to the same data storage, ie. _M_rep()->_M_is_shared() is
true.
Apart from the library version, the same thing happens with GCC 3.3.2.
I haven't tried the CVS version, but the reserve() code is the same.
With this modified code:
--
template<typename _CharT, typename _Traits, typename _Alloc>
void
basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
{
>> if (__res != this->capacity() || _M_rep()->_M_is_shared())
{
if (__res > this->max_size())
__throw_length_error("basic_string::reserve");
// Make sure we don't shrink below the current size
if (__res < this->size())
__res = this->size();
allocator_type __a = get_allocator();
_CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
_M_rep()->_M_dispose(__a);
_M_data(__tmp);
}
}
--
so that __res only needs to be different from capacity(), rather than
greater, I get the following output:
--
Version of libstdc++: 20031016
Initial capacity: 0
After 6 char assign: 6
After reserve(1000000): 1003491
After reserve(): 6
--
and a shrink-to-fit has occurred.
I'd be grateful for comments on the sensibility (or otherwise) of my
change to the reserve() method.
Thanks,
Neil.