For Programmers: Free Programming Magazines  


Home > Archive > VC STL > April 2005 > HELP :: STL Vectors in VC7 - behaviour changed for clear() reserve() and capacity() ?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author HELP :: STL Vectors in VC7 - behaviour changed for clear() reserve() and capacity() ?
Krishnan R.S.

2005-03-23, 4:01 am

Hello All,
I've got some code that used to work in VC6 but now asserts in VC7.

Code that used to work in VC6

---start snippet---
vector<int> my_vector;

/* setup some minimum amt of memory to allocate within the vector */
my_vector.reserve(10);
/* make sure there are no elems in the vector */
my_vector.clear();

assert( (my_vector.capacity() == 10) );

---end snippet---

Assuming that there are no memory exceptions my code above worked nicely in
VC6

With VC7 looks like the my_vector.clear() - clears the allocated/used
oprtion of the vector and also frees up the spare capacity we setup - i.e.
now capacity() returns me 0 with VC7 but used to be 10 with VC6.!!

I checked with the STL docs and this is not supposed to be the behaviour
......clear() only touches the used portions of the vector.

Anyone else seeing this behaviour in vc7 ?? Or am I doing something totally
wrong here ...

Thanks,
Krishnan




Carl Daniel [VC++ MVP]

2005-03-23, 4:01 am

Krishnan R.S. wrote:
> Hello All,
> I've got some code that used to work in VC6 but now asserts in VC7.
>
> Code that used to work in VC6
>
> ---start snippet---
> vector<int> my_vector;
>
> /* setup some minimum amt of memory to allocate within the vector */
> my_vector.reserve(10);
> /* make sure there are no elems in the vector */
> my_vector.clear();
>
> assert( (my_vector.capacity() == 10) );
>
> ---end snippet---
>
> Assuming that there are no memory exceptions my code above worked
> nicely in VC6
>
> With VC7 looks like the my_vector.clear() - clears the allocated/used
> oprtion of the vector and also frees up the spare capacity we setup -
> i.e. now capacity() returns me 0 with VC7 but used to be 10 with
> VC6.!!
>
> I checked with the STL docs and this is not supposed to be the
> behaviour .....clear() only touches the used portions of the vector.
>
> Anyone else seeing this behaviour in vc7 ?? Or am I doing something
> totally wrong here ...


Yes - you're relying on unspecified behavior.

std::vector<T>.clear() is defined to have a post condition of size()==0,
there's no guarantee that capacity() will have any particular value.
Logically, you could assume that it would either be 0 or the value that it
had before clear() was called, but neither of those is required.

If you want to erase all elements from a vector without changing capacity(),
you should use vec.erase(vec.begin(),vec.end()) instead of clear().

Note that clearing a vector right after default-constructing one (as in your
example above) is wasted effort - it's guaranteed to be empty on creation
unless you use one of the pre-filling constructors.

-cd


Krishnan R.S.

2005-03-23, 4:01 am

Hello Carl,

Ahhhh - somehow thought that clear was implemented as clear() { erase(
begin(), end() ); }

At least that's what I gathered from the often referenced SGI site ...

http://www.sgi.com/tech/stl/Vector.html

And

http://www.sgi.com/tech/stl/Sequence.html

If you look at clear() in the Sequence.htm link it essentially says that
clear() is an erase from begin() to end()

So calling erase() on the set of elems would not have changed much - or so
it seems ....

I guess that relying on clear() to remove only elems from the used part of
the vector was really non-standard!!

But they don't really say that capacity() will be affected in anyway - and
size() and capcity() were _meant_ to be different things!

But I'm glad to see that at least I'm not doing something that was
fundamentally wrong in vc7.

Thanks,

Krishnan

P.S.

====

Hmmmmm - vc7 yet to see some positive effects of this thing!!

--
"Krishnan R.S." <rskrishnan@hotmail.com> wrote in message
news:O5yvNI0LFHA.3616@TK2MSFTNGP09.phx.gbl...
> Hello All,
> I've got some code that used to work in VC6 but now asserts in VC7.
>
> Code that used to work in VC6
>
> ---start snippet---
> vector<int> my_vector;
>
> /* setup some minimum amt of memory to allocate within the vector */
> my_vector.reserve(10);
> /* make sure there are no elems in the vector */
> my_vector.clear();
>
> assert( (my_vector.capacity() == 10) );
>
> ---end snippet---
>
> Assuming that there are no memory exceptions my code above worked nicely

in
> VC6
>
> With VC7 looks like the my_vector.clear() - clears the allocated/used
> oprtion of the vector and also frees up the spare capacity we setup - i.e.
> now capacity() returns me 0 with VC7 but used to be 10 with VC6.!!
>
> I checked with the STL docs and this is not supposed to be the behaviour
> .....clear() only touches the used portions of the vector.
>
> Anyone else seeing this behaviour in vc7 ?? Or am I doing something

totally
> wrong here ...
>
> Thanks,
> Krishnan
>
>
>
>



Ken Alverson

2005-03-23, 4:01 pm

"Tom Widmer" <tom_usenet@hotmail.com> wrote in message
news:eL61tE5LFHA.3632@TK2MSFTNGP10.phx.gbl...
>
> I argued with the Dinkumware authors that this new behaviour was surprising
> to many users regardless of the exact wording of the standard, and they
> seemed to say that they would put it back the way it was before (e.g.
> clear() doesn't modify capacity()). Does anyone have a VC8 beta with which
> to confirm or deny this?


Judging by the number of times I've seen the "why doesn't my memory usage go
down when I call vector<>.clear(), the "old" behavior was surprising to many
users as well.

Ken


Carl Daniel [VC++ MVP]

2005-03-23, 4:01 pm

Tom Widmer wrote:
> I argued with the Dinkumware authors that this new behaviour was
> surprising to many users regardless of the exact wording of the
> standard, and they seemed to say that they would put it back the way
> it was before (e.g. clear() doesn't modify capacity()). Does anyone
> have a VC8 beta with which to confirm or deny this?


They did indeed put it back in VC8 - at least as of the Feb CTP.

-cd


Stephen Howe

2005-03-24, 4:00 am

> Well, the standard is not particularly well specified when it comes to the
> set of operations that can reduce the capacity of a vector.


And I regard that as deficiency with the standard.
Nothing wrong with VC6, VC7 or VC7.1 library in this regard.

Only the programmer knows from the code as to when any excess memory will no
longer needed.
There should be a shrink() function which miminises the amount of memory for
all standard containers (even things like deque as the array of pointers to
blocks of elements could be huge) rather than use things like the swap trick
which is non-binding on std::string. At that point the other member
functions can tightened as to so saying that excess memory won't be freed
(so it will be recycled in the event the programmer needs it for container
operations at a later point of execution).

Stephen Howe


Gene Bushuyev

2005-04-01, 4:03 pm

"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
wrote in message news:%237ZL4N0LFHA.3760@TK2MSFTNGP12.phx.gbl...
....
>
> Yes - you're relying on unspecified behavior.


I don't think so. Though it wasn't spelled out explicitly, I think it's
clear that the standard intention was to keep the allocation created by
reserve until the next reallocation.
23.2.4.2/2
"After reserve(), capacity() is greater or equal to the argument of reserve
if reallocation happens; and equal to the previous value of capacity()
otherwise. Reallocation happens at this point if and only if the current
capacity is less than the argument of reserve()."

23.2.4.2/5
"It is guaranteed that no reallocation takes place during insertions that
happen after a call to reserve() until the time when an insertion would make
the size of the vector greater than the size specified in the most recent
call to reserve()."

>
> std::vector<T>.clear() is defined to have a post condition of size()==0,
> there's no guarantee that capacity() will have any particular value.
> Logically, you could assume that it would either be 0 or the value that it
> had before clear() was called, but neither of those is required.
>
> If you want to erase all elements from a vector without changing

capacity(),
> you should use vec.erase(vec.begin(),vec.end()) instead of clear().


clear() is equivalent to erase(begin(), end()). See Table 67 - Sequence
requirements in 23.1.1

Gene


Gene Bushuyev

2005-04-01, 9:00 pm

"Ken Alverson" <USENET.Ken@Alverson.net> wrote in message news:eL$F%
....
> Judging by the number of times I've seen the "why doesn't my memory usage

go
> down when I call vector<>.clear(), the "old" behavior was surprising to

many
> users as well.


Surprising only to those who didn't care to read Herb Sutter's books. A
standard idiom to clear the content of a container and release the memory is
swap operation: std::vector<T>().swap(myvector);

Gene


Ken Alverson

2005-04-01, 9:00 pm

"Gene Bushuyev" <gb@127.0.0.1> wrote in message
news:Vjh3e.5633$FN4.3828@newssvr21.news.prodigy.com...
>
> Surprising only to those who didn't care to read Herb Sutter's books. A
> standard idiom to clear the content of a container and release the memory is
> swap operation: std::vector<T>().swap(myvector);


As you say, that is an idiom - something that is peculiar and surprising to
people who aren't intimately familiar with the language. Also, one could
consider Herb's solution a guarantee to the letter of the law that the memory
will be freed. That (by itself) doesn't preclude clear() from also freeing
memory.

Ken


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com