f



Which one(s) of the following std::vector's member functions has the possibility/authority to reduce the vector's capacity?

For C++11, I have 4 member functions in question:
template <class T, class Allocator = allocator<T> >
class vector {
public:
   vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
   vector<T,Allocator>& operator=(vector<T,Allocator>&& x);
   vector& operator=(initializer_list<T>);
   void clear() noexcept;
};

For C++03, I have 2 member function in question:
template <class T, class Allocator = allocator<T> >
class vector {
public:
   vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
   void clear();
};

Among these member functions, I'm quite confident about the last one, vector::clear() in C++03, because it's defined in terms of erase(begin(),end()) which is not allowed to change the capacity.  For the others, I can't find myself a reliable answer, so I'm asking for help here.  Relevant excerpts from the standard are highly appreciated.

Thanks,
goodbyeera


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
goodbyeera
3/10/2014 2:09:03 AM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8510) is leader. Post Follow

3 Replies
579 Views

Similar Articles

[PageSpeed] 14

Am 10.03.2014 09:09, schrieb goodbyeera@googlemail.com:
> For C++11, I have 4 member functions in question:
> template <class T, class Allocator = allocator<T> >
> class vector {
> public:
>     vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
>     vector<T,Allocator>& operator=(vector<T,Allocator>&& x);
>     vector& operator=(initializer_list<T>);
>     void clear() noexcept;
> };
>
> For C++03, I have 2 member function in question:
> template <class T, class Allocator = allocator<T> >
> class vector {
> public:
>     vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
>     void clear();
> };
>
> Among these member functions, I'm quite confident about the last one,
> vector::clear() in C++03, because it's defined in terms of
> erase(begin(),  end()) which is not allowed to change the capacity.

I should emphasize that in C++11 this connection got lost (I'm referring
for now to the current working draft N3936), due to

http://cplusplus.github.io/LWG/lwg-defects.html#704

You may notice that Table 100 now just says for expression "a.clear()":

"Destroys all elements in a. Invalidates all
references, pointers, and iterators referring to
the elements of a and may invalidate the
past-the-end iterator."

The intention has always been that clear() does not perform any
reallocation, but I would like to see that the wording would be clearer
for this.

> For the others, I can't find myself a reliable answer, so I'm asking for
> help here. Relevant excerpts from the standard are highly appreciated.

In C++11 the effects of the move/copy-assignment operators depends on
the nature of the allocators in source and target. This is specified in
[container.requirements.general] p8:

"[..] The allocator may be replaced only via assignment or swap().
Allocator replacement is performed by copy assignment, move assignment,
or swapping of the allocator only if
allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value,
allocator_traits<allocator_type>::propagate_on_container_move_assignment::value,
or allocator_traits<allocator_type>::propagate_on_container_swap::value
is true within the implementation of the corresponding container
operation. [..]"

The implication of this wording is that if allocator replacement happens
during copy/move assignment, then the previous storage must be freed
(and thus the capacity reduced to zero during the operation which
corresponds to an effective reduction of the capacity). It is IMO not
really clear from the wording, whether in such a situation an
implementation is required or allowed to check for allocator equality
when propagate_on_container_copy/move_assignment return true and to
finally decide on reallocation depending on the outcome of that test.

In regard to

vector& operator=(initializer_list<T>);

the wording state of Table 100, expression "a = il" imposes the
requirement that no capacity reduction shall happen:

"[..] Assigns the range [il.begin(),il.end()) into a. All existing
elements of a are either assigned to or destroyed. [..]"

The full conclusion on the effects of capacity seems to be covered by
the general specification of vector's reallocation strategy described in
[vector.capacity] (reserve).

HTH & Greetings from Bremen,

Daniel Kr�gler


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
windows
3/11/2014 2:16:45 AM
W dniu poniedziałek, 10 marca 2014 08:10:02 UTC+1 użytkownik goodb...@googlemail.com napisał:
> For C++11, I have 4 member functions in question:
> 
>    vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
>    vector<T,Allocator>& operator=(vector<T,Allocator>&& x);
>    vector& operator=(initializer_list<T>);
>    void clear() noexcept;
> 
You forget about swap() function. The only way I know to reduce vector
capcity is to swap with empty vector:

vector<int> v(30);
assert(v.capacity()>=30);
vector<int>().swap(v);
assert(v.capacity() == vector<int>().capacity());

BR,
Piotr


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Piotr
3/12/2014 6:32:31 PM
{ new text reformatted to fit in ~70 characters per line.  quoting
  left as is to draw the poster's attention to formatting. -mod }

On Tuesday, March 11, 2014 3:20:01 PM UTC+8, Daniel Kr�gler wrote:
> In C++11 the effects of the move/copy-assignment operators depends on
> 
> the nature of the allocators in source and target. This is specified in
> 
> [container.requirements.general] p8:
> 
> 
> 
> "[..] The allocator may be replaced only via assignment or swap().
> 
> Allocator replacement is performed by copy assignment, move assignment,
> 
> or swapping of the allocator only if
> 
>
allocator_traits<allocator_type>::propagate_on_container_copy_assignment::va
lue,
> 
>
allocator_traits<allocator_type>::propagate_on_container_move_assignment::va
lue,
> 
> or allocator_traits<allocator_type>::propagate_on_container_swap::value
> 
> is true within the implementation of the corresponding container
> 
> operation. [..]"
> 
> 
> 
> The implication of this wording is that if allocator replacement happens
> 
> during copy/move assignment, then the previous storage must be freed
> 
> (and thus the capacity reduced to zero during the operation which
> 
> corresponds to an effective reduction of the capacity). It is IMO not
> 
> really clear from the wording, whether in such a situation an
> 
> implementation is required or allowed to check for allocator equality
> 
> when propagate_on_container_copy/move_assignment return true and to
> 
> finally decide on reallocation depending on the outcome of that test.
> 
> 

Hi Daniel,

Thank you very much for replying with detailed information.  I think
I'm now clear regarding vector::clear() and
vector::operator=(initializer_list<T>).

For copy/move assignment, I now understand that when allocator
replacement happens, reallocation and reduction of capacity may well
happen.  But what if
allocator_traits<allocator_type>::propagate_on_container_copy_assignment()/a
llocator_traits<allocator_type>::propagate_on_container_move_assignment()
is false (and in the case of move assignment, the target and source
allocator does not compare equal), can we be assured that reduction of
capacity won't take place?

Thanks,
Goodbyeera


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
goodbyeera
3/13/2014 2:33:31 PM
Reply: