Topic: vector::resize - pass by value?


Author: dHarrison@worldnet.att.net (Doug Harrison)
Date: 1997/01/16
Raw View
On 15 Jan 1997 15:36:21 PST, dag@net.dynasim.se (Dag Bruck) wrote:

>In article <32DAF895.4DC6@gim.net>, Bill Dimm  <billd@gim.net> wrote:
>>The Apr 95 draft, section 23.2.5.4, shows the declaration
>>of vector::resize as:
>>   void resize(size_type sz, T c = T());
>>Has this been changed to:
>>   void resize(size_type sz, const T &c = T());
>>in more recent drafts?  If not, why is the argument passed
>>by value here?
>
>Consider this case:
>
> vector<int> v(10); // Initial size 10 elements
> v.resize(1000, v[0]); // Grow and init. with first element
>
>The resize operation may reallocate the representation of the
>vector, which means that the reference to v[0] would no longer
>be valid.  Passing "c" by value avoids this problem at a small
>cost.

What about:

 iterator insert(iterator position, const T& x = T());

I find no restriction on the source of 'x' in the Apr-95 DWP. If the
language concerning the invalidation of iterators and references is
intended to imply 'x' can't refer to an element of the vector, then
it's a bit subtle. And I don't think it would be hard or inefficient
in the slightest to support an 'x' that is a reference to an element
of the vector, especially if you want to ensure a failed insert() or
resize() at worst leaves the vector in a state equivalent to its
original state.

Also, list<> declares its resize() the same way as vector, and the
documentation describes the effects of a resize() that grows the list
in terms of insert(), which "does not affect the validity of iterators
or references". It seems to me that list's resize() could thus use a
const reference parameter.

--
Doug Harrison
dHarrison@worldnet.att.net
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Bill Dimm <billd@gim.net>
Date: 1997/01/14
Raw View
The Apr 95 draft, section 23.2.5.4, shows the declaration
of vector::resize as:
   void resize(size_type sz, T c = T());
Has this been changed to:
   void resize(size_type sz, const T &c = T());
in more recent drafts?  If not, why is the argument passed
by value here?
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: dHarrison@worldnet.att.net (Doug Harrison)
Date: 1997/01/14
Raw View
On 14 Jan 97 03:58:22 GMT, Bill Dimm <billd@gim.net> wrote:

>The Apr 95 draft, section 23.2.5.4, shows the declaration
>of vector::resize as:
>   void resize(size_type sz, T c = T());
>Has this been changed to:
>   void resize(size_type sz, const T &c = T());
>in more recent drafts?  If not, why is the argument passed
>by value here?

I've wondered about this too, and I would guess that since growing a
vector will require copy construction of new elements anyway, it
doesn't much matter if 'c' is passed by value or const reference.
Passing by value implies making only one additional copy, and it might
even allow more efficient copy construction of the new elements
(though I'm doubtful about this last point in general). In other
words, if you can afford to grow a vector, possibly reallocating its
storage, then you shouldn't be too worried about making one T copy
more than may strictly be necessary.

However, resize() can also be used to shrink a vector. Shrinking
doesn't require a T object at all, and it's wasteful and a little
inappropriate that resize() requires construction of one. But if
avoiding construction of the superfluous T is that important, you can
always use erase().

I think the definition of resize() makes some not-so-subtle
suggestions about what a resizable vector should contain, and how it
should be resized, and I mostly agree. However, if you were to define
resize() as follows:

 void resize(size_type sz)
 {
    if (sz > size())
       insert( ... T() ... );
    else if (sz < size())
       erase(...);
 }
 void resize(size_type sz,T c)
 {
    if (sz > size())
       insert( ... c ... );
    else if (sz < size())
       erase(...);
 }

then you can avoid unnecessarily constructing a T when shrinking the
container. In fact, I had to do something similar to avoid compiler
bugs resulting from the default parameter.

--
Doug Harrison
dHarrison@worldnet.att.net


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]