By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,928 Members | 1,210 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,928 IT Pros & Developers. It's quick & easy.

resize and clear of vector

P: n/a
Hi,
I am using a vector to reserve certain amount of memory, and reuse
it for new set of data, to avoid reallocation of memory.
so the call is something like
vector<my_datav;///the temporary storage.
v.reserve(300); ///at max I have 300 data.

now, my_data doesn't have a default ctor (as it doesn't have a default
state).

to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
3) do a resize with a size smaller than existing size requires
default (or any other ctor ) ?

thanks

Mar 21 '07 #1
Share this Question
Share on Google+
17 Replies


P: n/a
toton wrote:
1) do clear zero's capacity , i.e frees memory?
No. std::vector never frees memory (except when it's destroyed,
of course).
2) do resize to a size smaller than existing size reduces capacity
No.

If you want to free the memory taken by a std::vector, there's
a known trick for that:

{
std::vector<my_datatmp;
v.swap(tmp);
}
// Here 'v' will have 0 size and will have no memory allocated

Note that the curly brackets are very relevant there.
Mar 21 '07 #2

P: n/a
toton a écrit :
Hi,
I am using a vector to reserve certain amount of memory, and reuse
it for new set of data, to avoid reallocation of memory.
so the call is something like
vector<my_datav;///the temporary storage.
v.reserve(300); ///at max I have 300 data.

now, my_data doesn't have a default ctor (as it doesn't have a default
state).

to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
It is not required by the standard thus AFAIK existing implementations
don't.
2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
It is not required by the standard thus AFAIK existing implementations
don't.
3) do a resize with a size smaller than existing size requires
default (or any other ctor ) ?
No reason it should.

The usual trick to release memory of a vector is:
vector<myClassmy_vector(100000);

//clear by swapping with empty vector
std::vector<myClass>().swap(my_vector);
Michael
Mar 21 '07 #3

P: n/a
toton a écrit :
Hi,
I am using a vector to reserve certain amount of memory, and reuse
it for new set of data, to avoid reallocation of memory.
so the call is something like
vector<my_datav;///the temporary storage.
v.reserve(300); ///at max I have 300 data.

now, my_data doesn't have a default ctor (as it doesn't have a default
state).
[snip]
3) do a resize with a size smaller than existing size requires
default (or any other ctor ) ?
I don't understand your concern about default constructor.

std::vector doesn't require a default constructor. You can pass the
object to use for construction as second parameter.

vector<my_datav(10,my_data(42);

The same is true of resize:
v.resize(72,my_data(36);

Michael
Mar 21 '07 #4

P: n/a
On Mar 21, 1:12 pm, Juha Nieminen <nos...@thanks.invalidwrote:
toton wrote:
1) do clear zero's capacity , i.e frees memory?

No. std::vector never frees memory (except when it's destroyed,
of course).
2) do resize to a size smaller than existing size reduces capacity

No.

If you want to free the memory taken by a std::vector, there's
a known trick for that:

{
std::vector<my_datatmp;
v.swap(tmp);
}
// Here 'v' will have 0 size and will have no memory allocated

Note that the curly brackets are very relevant there.
Thanks,
The trick works.
But, as I am not interested to release memory (except destructor of
course ) , as your post says clear doesn't release memory.
However , from this code it gives output ,
vector<intvi(10) ;
cout<<"sz "<<vi.size()<<" cap "<<vi.capacity()<<endl; (size &
capacity 10, as expected)
std::generate(vi.begin(),vi.end(),rand);
cout<<endl; for_each(vi.begin(),vi.end(),cout<<_1<<" ");
cout<<"sz "<<vi.size()<<" cap "<<vi.capacity()<<endl; (size &
capacity 10, as expected)
vi.clear();
cout<<"sz "<<vi.size()<<" cap "<<vi.capacity()<<endl; (size &
capacity 0, I expected size = 0 while capacity 10)
However the statement vi.resize(0); makes size 0 , capacity 10.
so, as I don't want to release memory except destructor ,
1) which never releases memory resize(0) or clear() ?
2) the capacity is giving a wrong result ?
3) result of clear (and/or) resize whether to release memory is
implementation dependent ?
I am using Visual Studio 7.1 with MS implementation of std lib.

thanks
abir


Mar 21 '07 #5

P: n/a
Michael DOUBEZ wrote:
>to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
It is not required by the standard thus AFAIK existing implementations
don't.
Actually, the standard requires that this is not done.
> 2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
It is not required by the standard thus AFAIK existing implementations
don't.
Actually, the standard requires that this is not done.

Mar 21 '07 #6

P: n/a
On Mar 21, 2:33 pm, Rolf Magnus <ramag...@t-online.dewrote:
Michael DOUBEZ wrote:
to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.
2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.
When I go through the MS implementation (VS 7.1 ) of STL, clear looks
like,
void clear()
{ // erase all
_Tidy();
}
void _Tidy()
{ // free all storage
if (_Myfirst != 0)
{ // something to free, destroy and deallocate it
_Destroy(_Myfirst, _Mylast);
this->_Alval.deallocate(_Myfirst, _Myend - _Myfirst);///check this
line. it deallocates
}
_Myfirst = 0, _Mylast = 0, _Myend = 0;
}
Thus it removes memory (deallocates) not only destroys. That is why
capacity comes as 0 after clear. However it is not same for resize(0),
where it doesn't call deallocate (only construct or destroy) .
The results are given in my previous post.
Is it wrong according to std ? or just implementation defined ?
Thus which of the two (clear / resize(0) ) NEVER releases memory
according to std , if any one of them do at all.

thanks
abir

Mar 21 '07 #7

P: n/a
toton wrote:
On Mar 21, 2:33 pm, Rolf Magnus <ramag...@t-online.dewrote:
>Michael DOUBEZ wrote:
>to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.
> 2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.

When I go through the MS implementation (VS 7.1 ) of STL, clear looks
like,
void clear()
{// erase all
_Tidy();
}
void _Tidy()
{// free all storage
if (_Myfirst != 0)
{ // something to free, destroy and deallocate it
_Destroy(_Myfirst, _Mylast);
this->_Alval.deallocate(_Myfirst, _Myend - _Myfirst);///check this
line. it deallocates
}
_Myfirst = 0, _Mylast = 0, _Myend = 0;
}
Seems to be a violation of the C++ standard.
Thus it removes memory (deallocates) not only destroys. That is why
capacity comes as 0 after clear. However it is not same for resize(0),
where it doesn't call deallocate (only construct or destroy) .
The results are given in my previous post.
Is it wrong according to std ? or just implementation defined ?
The C++ standard says that for any sequence a, a.clear() should do the
equivalent to a.erase(a.begin(), a.end()). The description of the effects
of std::vector::erase doesn't mention any change in capacity/reallocation.
Thus which of the two (clear / resize(0) ) NEVER releases memory
according to std , if any one of them do at all.
The standard says that the behavior of resize() if the new size is less than
the old one is equivalent to the corresponding erase() call. Since that's
also the case for clear(), both must have exactly the same result in a
conforming implementation.

Mar 21 '07 #8

P: n/a
Rolf Magnus a écrit :
Michael DOUBEZ wrote:
>>to use vector v again and again,
I am doing ,
v.resize(0);
////and then use it. I can do v.clear() for better.
Now the questions are,
1) do clear zero's capacity , i.e frees memory? (Then I can't use it,
as it iteration the vector will reallocate memory)
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.
>> 2) do resize to a size smaller than existing size reduces capacity
(Then resize(0) will also do the same thing )
It is not required by the standard thus AFAIK existing implementations
don't.

Actually, the standard requires that this is not done.
I could not find the relevant requirement in the standard.
Can you or anyone provide it ?

Michael
Mar 21 '07 #9

P: n/a
>Actually, the standard requires that this is not done.

Where? The standard is silent on this. The standard is inadeqate.
Seems to be a violation of the C++ standard.
No. The standard neither forbids nor blesses the practice.
Therefore it is implementation defined.
The standard says that the behavior of resize() if the new size is less
than
the old one is equivalent to the corresponding erase() call. Since that's
also the case for clear(), both must have exactly the same result in a
conforming implementation.
Yes. Which does not say anything about what happens to the memory.

Stephen Howe

Mar 21 '07 #10

P: n/a
>Actually, the standard requires that this is not done.
>
I could not find the relevant requirement in the standard.
Can you or anyone provide it ?
He is incorrect. It is not there.
The standard is _silent_ on what happens to memory and that means it is
implementation defined.

Stephen Howe
Mar 21 '07 #11

P: n/a
"Stephen Howe" <sjhoweATdialDOTpipexDOTcomwrote:
>>Actually, the standard requires that this is not done.

Where? The standard is silent on this. The standard is inadeqate.
It gives information about the effects that erase() has, and re-allocation
is not one of those, so it doesn't happen. Invalidation of iterators to the
erased elements and those after it is an effect, but invalidation of those
before is not. A re-allocation would invalidate all iterators, so it can't
happen.
What makes you believe it's optional?
>The standard says that the behavior of resize() if the new size is less
than the old one is equivalent to the corresponding erase() call. Since
that's also the case for clear(), both must have exactly the same result
in a conforming implementation.

Yes. Which does not say anything about what happens to the memory.
It says that the implementation the OP is using is non-conforming, because
the behavor of resize(0) is different from that of clear().

Mar 21 '07 #12

P: n/a
"Rolf Magnus" <ra******@t-online.dewrote in message
news:et************@news.t-online.com...
"Stephen Howe" <sjhoweATdialDOTpipexDOTcomwrote:
>>>Actually, the standard requires that this is not done.

Where? The standard is silent on this. The standard is inadeqate.

It gives information about the effects that erase() has, and re-allocation
is not one of those, so it doesn't happen. Invalidation of iterators to
the
erased elements and those after it is an effect, but invalidation of those
before is not. A re-allocation would invalidate all iterators, so it can't
happen.
What makes you believe it's optional?
>>The standard says that the behavior of resize() if the new size is less
than the old one is equivalent to the corresponding erase() call. Since
that's also the case for clear(), both must have exactly the same result
in a conforming implementation.

Yes. Which does not say anything about what happens to the memory.

It says that the implementation the OP is using is non-conforming, because
the behavor of resize(0) is different from that of clear().
Actually, it says nothing of the sort. But there was a Defect Report
asking for clarification, and the Library Working Group chose to
clarify the matter by ruling that the library can't reduce the
capacity on a clear. That ruling came down after VC++ V7.1 froze,
but you'll find the now "correct" behavior in VC++ V8.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Mar 21 '07 #13

P: n/a
P.J. Plauger wrote:
>>>The standard says that the behavior of resize() if the new size is less
than the old one is equivalent to the corresponding erase() call. Since
that's also the case for clear(), both must have exactly the same
result in a conforming implementation.

Yes. Which does not say anything about what happens to the memory.

It says that the implementation the OP is using is non-conforming,
because the behavor of resize(0) is different from that of clear().

Actually, it says nothing of the sort.
Table 67 says that the effect of clear() for sequences is the same as
erase(begin(), end()), and 23.2.4.2 says that resize(sz) has the same
effect as:

if (sz size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end());
else
; // do nothing
so doesn't that mean that clear() has the same effect as resize(0)?

Mar 21 '07 #14

P: n/a
"Rolf Magnus" <ra******@t-online.dewrote in message
news:et*************@news.t-online.com...
P.J. Plauger wrote:
>>>>The standard says that the behavior of resize() if the new size is
less
than the old one is equivalent to the corresponding erase() call.
Since
that's also the case for clear(), both must have exactly the same
result in a conforming implementation.

Yes. Which does not say anything about what happens to the memory.

It says that the implementation the OP is using is non-conforming,
because the behavor of resize(0) is different from that of clear().

Actually, it says nothing of the sort.

Table 67 says that the effect of clear() for sequences is the same as
erase(begin(), end()), and 23.2.4.2 says that resize(sz) has the same
effect as:

if (sz size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end());
else
; // do nothing
so doesn't that mean that clear() has the same effect as resize(0)?
The issue in question was whether, under any circumstances, vector
could reduce capacity. The C++ Standard just didn't say. The LWG,
after some discussion, determined that clear should not reduce
capacity (even though it doesn't explicitly say that it can't) but
swap should (even though it doesn't explicitly say that it can).
IOW, the current rule is an *interpretation* of what should be
desired behavior.

Many years ago, I had several requests from customers for some way
to reduce the capacity of a vector. Absent clear guidance from the
C++ Standard, I picked a way and those customers were happy. When
the LWG made a different rule, the Dinkumware library changed to
match the new rule. You can persist all you want in asserting that
the answer is obvious in hindsight, but we did have to guess.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Mar 21 '07 #15

P: n/a
P.J. Plauger wrote:
"Rolf Magnus" <ra******@t-online.dewrote in message
news:et*************@news.t-online.com...
>P.J. Plauger wrote:
>>>>>The standard says that the behavior of resize() if the new size is
>less than the old one is equivalent to the corresponding erase()call.
>Since that's also the case for clear(), both must have exactly the
>same result in a conforming implementation.
>
Yes. Which does not say anything about what happens to the memory.

It says that the implementation the OP is using is non-conforming,
because the behavor of resize(0) is different from that of clear().

Actually, it says nothing of the sort.

Table 67 says that the effect of clear() for sequences is the same as
erase(begin(), end()), and 23.2.4.2 says that resize(sz) has the same
effect as:

if (sz size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end());
else
; // do nothing
so doesn't that mean that clear() has the same effect as resize(0)?

The issue in question was whether, under any circumstances, vector
could reduce capacity.
We had two issues here. The second one is if resize(0) may behave
differently than clear(), and C++98 explicitly says that this is not
allowed.
The C++ Standard just didn't say.
I was assuming that it's enough that a reallocation is not mentioned as an
effect of erase(). It could have been more explicit though.
The LWG, after some discussion, determined that clear should not reduce
capacity (even though it doesn't explicitly say that it can't) but swap
should (even though it doesn't explicitly say that it can).
The 98 version of the standard (the only one available to me ATM) forbids
that. Was it changed in the 03 version?
IOW, the current rule is an *interpretation* of what should be desired
behavior.
I really hate it if a standard must be interpreted.

Mar 23 '07 #16

P: n/a
Rolf Magnus wrote:
:: P.J. Plauger wrote:
::
::: "Rolf Magnus" <ra******@t-online.dewrote in message
::: news:et*************@news.t-online.com...
:::
:::
::: The issue in question was whether, under any circumstances, vector
::: could reduce capacity.
::
:: We had two issues here. The second one is if resize(0) may behave
:: differently than clear(), and C++98 explicitly says that this is not
:: allowed.
::
::: The C++ Standard just didn't say.
::
:: I was assuming that it's enough that a reallocation is not mentioned
:: as an effect of erase(). It could have been more explicit though.
::
::: The LWG, after some discussion, determined that clear should not
::: reduce capacity (even though it doesn't explicitly say that it
::: can't) but swap should (even though it doesn't explicitly say that
::: it can).
::
:: The 98 version of the standard (the only one available to me ATM)
:: forbids that. Was it changed in the 03 version?
::
::: IOW, the current rule is an *interpretation* of what should be
::: desired behavior.
::
:: I really hate it if a standard must be interpreted.

It is not really an interpretation, but a clarification. :-)

From what I understand, the original question was about the standard saying
that after a call to reserve(x), the capacity can never go below x. But what
if reserve() is never called, can the capacity shrink then?

And the clarification is: No!
The only sort-of-exception is swap, which sort of reduces the capacity, but
can also be seen as only transferring it elsewhere.

Bo Persson
Mar 24 '07 #17

P: n/a
Bo Persson wrote:
Rolf Magnus wrote:
:: P.J. Plauger wrote:
::
::: "Rolf Magnus" <ra******@t-online.dewrote in message
::: news:et*************@news.t-online.com...
:::
:::
::: The issue in question was whether, under any circumstances, vector
::: could reduce capacity.
::
:: We had two issues here. The second one is if resize(0) may behave
:: differently than clear(), and C++98 explicitly says that this is not
:: allowed.
::
::: The C++ Standard just didn't say.
::
:: I was assuming that it's enough that a reallocation is not mentioned
:: as an effect of erase(). It could have been more explicit though.
::
::: The LWG, after some discussion, determined that clear should not
::: reduce capacity (even though it doesn't explicitly say that it
::: can't) but swap should (even though it doesn't explicitly say that
::: it can).
::
:: The 98 version of the standard (the only one available to me ATM)
:: forbids that. Was it changed in the 03 version?
::
::: IOW, the current rule is an *interpretation* of what should be
::: desired behavior.
::
:: I really hate it if a standard must be interpreted.

It is not really an interpretation, but a clarification. :-)
Well, if there are different views, it's an interpretation.
From what I understand, the original question was about the standard
saying that after a call to reserve(x), the capacity can never go below x.
But what if reserve() is never called, can the capacity shrink then?

And the clarification is: No!
My impression was that swap() was guaranteed to reduce the capacity and
everything else was guaranteed not to. I thought that was absolutely clear,
considering that I read something like that quite often here and elsewhere.
I'm not so sure now, since there seem to be different opinions, and the
standard is not really fully clear about it.
The only sort-of-exception is swap, which sort of reduces the capacity,
but can also be seen as only transferring it elsewhere.
Actually, I didn't find anything in the standard that says so, but maybe I
just missed it. Could you give chapter/verse?

Mar 24 '07 #18

This discussion thread is closed

Replies have been disabled for this discussion.