Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sequence container capacity after calling clear()

107 views
Skip to first unread message

Leigh Johnston

unread,
Mar 23, 2013, 6:27:46 PM3/23/13
to

Hi,

Can we please change the ISO C++ Standard so that explicitly states what
happens to a sequence container's capacity() after calling clear()?

Currently the behaviour is unspecified and I know of at least one
implementation that deallocates on vector<T>::clear().

If the behaviour remains unspecified then it is effectively impossible
to write portable code that uses clear() and you have to hope things
such as v.erase(v.begin(), v.end()) behave more consistently across
different implementations.

/Leigh


--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp...@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

Daniel Krügler

unread,
Mar 24, 2013, 1:05:32 AM3/24/13
to
Am 23.03.2013 23:27, schrieb Leigh Johnston:
>
>
> Can we please change the ISO C++ Standard so that explicitly states what
> happens to a sequence container's capacity() after calling clear()?
>
> Currently the behaviour is unspecified and I know of at least one
> implementation that deallocates on vector<T>::clear().
>
> If the behaviour remains unspecified then it is effectively impossible
> to write portable code that uses clear() and you have to hope things
> such as v.erase(v.begin(), v.end()) behave more consistently across
> different implementations.


This problem was already cause of a previous library issue:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#1102

Please provide this link to the vendor of the buggy library you have in mind.

HTH & Greetings from Bremen,

Daniel Kr�gler

Jason McKesson

unread,
Mar 24, 2013, 1:05:54 AM3/24/13
to
On Saturday, March 23, 2013 2:30:03 PM UTC-7, Leigh Johnston wrote:
> Hi,
>
>
>
> Can we please change the ISO C++ Standard so that explicitly states what
>
> happens to a sequence container's capacity() after calling clear()?
>
>
>
> Currently the behaviour is unspecified and I know of at least one
>
> implementation that deallocates on vector<T>::clear().
>
>
>
> If the behaviour remains unspecified then it is effectively impossible
>
> to write portable code that uses clear() and you have to hope things
>
> such as v.erase(v.begin(), v.end()) behave more consistently across
>
> different implementations.

I don't see what's non-portable about this.

If you don't care what the capacity is, you use `clear` and let the
implementation decide. It's not non-portable because your code
*doesn't care*. If you *do* care about the capacity, then you either
want the capacity to be zeroed out or you want it to be preserved. And
you already have the tools to do either:

vec.resize(0); //Destroys contents, but doesn't change the capacity.
vec = vector<T>{}; //Destroys contents and reduces the capacity.

Both of these are reasonable behaviors, so the user should be able to
do either if they want a specific result.

Juha Nieminen

unread,
Mar 25, 2013, 2:36:42 AM3/25/13
to
In comp.lang.c++ Leigh Johnston <le...@i42.co.uk> wrote:
> Currently the behaviour is unspecified and I know of at least one
> implementation that deallocates on vector<T>::clear().

One would think that such an implementation would get so many complaints
that they would fix that.

I don't think it's extremely rare for people to use std::vector as a
buffer to do some data manipulation. If said code is called very
frequently, then allocating a new array every single time would have
a really big impact on performance, so it's better to reuse the one
and same std::vector instance each time (by either making it 'static'
if it's inside the function, a member function of the class, if this
is a class, or a compilation-unit-local object.)

If this is so, then usually you want to clear the vector before
doing anything with it, so that it doesn't contain anything from the
previous run (assuming that you don't know in advance how many elements
there will be in the vector.)

If the vector implementation works as usual, this is a fast operation
because a 'clear()' will simply destroy the objects and set the size
to zero, but not actually free the memory. Thus it will work as a
static memory buffer.

However, if 'clear()' frees the memory, that means that there will be
a deallocation and an allocation every single time that the function is
called, having a big impact in performance. The only way to make sure
that this doesn't happen is to bypass std::vector and make your own
class which manages a dynamic array. The value of std::vector as a
useful tool has thus been diminished.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Mathias Gaunard

unread,
Mar 25, 2013, 12:49:44 PM3/25/13
to

On Mar 23, 10:30 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> Hi,
>
> Can we please change the ISO C++ Standard so that explicitly states what
> happens to a sequence container's capacity() after calling clear()?
>
> Currently the behaviour is unspecified and I know of at least one
> implementation that deallocates on vector<T>::clear().
>
> If the behaviour remains unspecified then it is effectively impossible
> to write portable code that uses clear() and you have to hope things
> such as v.erase(v.begin(), v.end()) behave more consistently across
> different implementations.

Use shrink_to_fit if you want to reduce capacity to 0 after a clear.

Leigh Johnston

unread,
Mar 26, 2013, 10:55:38 AM3/26/13
to

On 25/03/2013 16:49, Mathias Gaunard wrote:
>
> On Mar 23, 10:30 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>> Hi,
>>
>> Can we please change the ISO C++ Standard so that explicitly states what
>> happens to a sequence container's capacity() after calling clear()?
>>
>> Currently the behaviour is unspecified and I know of at least one
>> implementation that deallocates on vector<T>::clear().
>>
>> If the behaviour remains unspecified then it is effectively impossible
>> to write portable code that uses clear() and you have to hope things
>> such as v.erase(v.begin(), v.end()) behave more consistently across
>> different implementations.
>
> Use shrink_to_fit if you want to reduce capacity to 0 after a clear.

You didn't grok my post properly. I want the opposite: I want the
capacity to be unchanged after calling clear().

/Leigh

James Kanze

unread,
Mar 27, 2013, 3:28:17 PM3/27/13
to

On Sunday, 24 March 2013 05:05:32 UTC, Daniel Krügler wrote:
> Am 23.03.2013 23:27, schrieb Leigh Johnston:
> > Can we please change the ISO C++ Standard so that explicitly states what
> > happens to a sequence container's capacity() after calling clear()?

> > Currently the behaviour is unspecified and I know of at least one
> > implementation that deallocates on vector<T>::clear().

> > If the behaviour remains unspecified then it is effectively impossible
> > to write portable code that uses clear() and you have to hope things
> > such as v.erase(v.begin(), v.end()) behave more consistently across
> > different implementations.

> This problem was already cause of a previous library issue:

> http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#1102

> Please provide this link to the vendor of the buggy library you have in mind.

I, for one, would like to see the issue reopened. I understand
the logic behind the current resolution, but I think it is less
than clear. Particularly because:

1. The guarantees with regards to the validity of iterators and
the absense of reallocation are given with regards to
a previous call to reserve. In other words, clear() cannot
reduce the capacity IF the capacity was the result of a call
to reserve. Now, we all know that no implementation is
going to make clear() behave differently depending on
whether reserve() was called or not, but technically, it
might be legal.

2. C++11 has changed the definition of clear(). It used to be
defined in terms of erase(); erase() is documented to only
invalidate iterators at or after the elements which are
erased. Logically, I suppose that one could argue that if
all of the elements are erased, it could invalidate all
iterators, but again, one would not expect such special
casing, and it would seem to violate at least the intent of
the standard. Now that clear() is no longer defined in
terms of erase(), however, such indirect argumentation is
seriously weakened.

I'd really like to see this specified a bit clearer, even if
there seems to be a consensus in the committee as to what is
meant. (I noticed that C++11 also reduces guarantees elsewhere,
and has rendered an expression like s[i] == s[j] invalid if s is
a non-const std::string. Luckily, all of the implementors seem
to know what is wanted, and implement something reasonable, but
still, it would be nice to have it guaranteed.)

--
James
0 new messages