Topic: state of vector after default constructor
Author: Barry Fortune <joburg@interpow.net>
Date: 1997/03/21 Raw View
I have just switched to Microsoft VC++ ver 5.0 and have come across the
following problem with a
vector.
1. I construct a vector with default constructor eg
vector<char> x;
2. I invoke a copy algorithm eg
string s = "abc";
copy(s.begin(), s.end(), x.end());
What happens is that the default constructor for vector does no
allocation - just set pointers to nulls.
(PJ Plauger's code is used by this implementation).
Then x.end() is a null pointer, so the copy tries to dereference a null
pointer and an exception is thrown.
Is this the correct behaviour for the default constructor to vector - or
is it supposed to be ready to
handle an immediate copy.
Many thanks,
Barry Fortune.
---
[ 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: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/21 Raw View
Barry Fortune <joburg@interpow.net> writes:
>1. I construct a vector with default constructor eg
> vector<char> x;
>2. I invoke a copy algorithm eg
> string s = "abc";
> copy(s.begin(), s.end(), x.end());
>
>What happens is that the default constructor for vector does no
>allocation - just set pointers to nulls. [...]
>Then x.end() is a null pointer, so the copy tries to dereference a null
>pointer and an exception is thrown.
>
>Is this the correct behaviour for the default constructor to vector -
Yes, that is correct behaviour. Your call to copy() has undefined
behaviour. If you want to copy data into an empty vector, you need to
use an insert iterator, e.g.
copy(s.begin(), s.end(), insert_iterator(x.end()));
or
copy(s.begin(), s.end(), back_iterator(x));
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ 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: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: 1997/03/21 Raw View
Hi,
Barry Fortune (joburg@interpow.net) wrote:
: 1. I construct a vector with default constructor eg
: vector<char> x;
: 2. I invoke a copy algorithm eg
: string s = "abc";
: copy(s.begin(), s.end(), x.end());
This does not work! 'x' contains no element where the contents of 's'
can be assigned to. It is correct behavior of the 'vector' to have a
size of '0'. To copy into an empty 'vector' (or 'list', 'deque',...),
you can use this:
copy(s.begin(), s.end(), back_inserter(x));
which is just a short cut for
copy(s.begin(), s.end(), back_insert_iterator<vector<int> >(x));
This will use the method 'push_back()' of the corresponding container
to insert the elements.
: Is this the correct behaviour for the default constructor to vector - or
: is it supposed to be ready to
: handle an immediate copy.
Non of the standard container is ever ready to be used to "handle
immediate copy" in the way you did it above. The 'copy()' (without
using a specialized iterator like 'back_insert_iterator') works only if
the destination has at least as many elements as the source. Using a
'back_insert_iterator' as the destination solves this problem by
increasing the size of the use container correspondingly.
--
<mailto:dietmar.kuehl@uni-konstanz.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ 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: Matt Austern <austern@sgi.com>
Date: 1997/03/21 Raw View
Barry Fortune <joburg@interpow.net> writes:
> I have just switched to Microsoft VC++ ver 5.0 and have come across the
> following problem with a
> vector.
>
> 1. I construct a vector with default constructor eg
> vector<char> x;
> 2. I invoke a copy algorithm eg
> string s = "abc";
> copy(s.begin(), s.end(), x.end());
>
> What happens is that the default constructor for vector does no
> allocation - just set pointers to nulls.
> (PJ Plauger's code is used by this implementation).
> Then x.end() is a null pointer, so the copy tries to dereference a null
> pointer and an exception is thrown.
>
> Is this the correct behaviour for the default constructor to vector - or
> is it supposed to be ready to
> handle an immediate copy.
Yes, this is correct behavior. You will get a crash of one sort or
another from any STL implementation; Microsoft's libraries aren't
unique in this respect.
The problem is that when the vector is initially created, it has
size zero. If you want it to hold three characters, it has to be
of at least size 3. So somehow, its size has to be expanded.
Copy() does not expand the size of whatever it's copying into. This
might seem at first like a terrible restriction, but, when you think
about it, you'll see that it's really quite inevitable. Copy()
doesn't know about vectors or strings, or anything like that; it only
knows about iterators. It assigns through the first iterator,
increments it, assigns to the second iterator, increments it, and so
on. It doesn't call any of x's member functions, and, since x is not
passed as an argument, there is no way that it possibly could.
[Oh, and one other small problem with this code: it's being passed a
copy of x.end(). Even if x had a nonzero size, that still wouldn't
work. x.end() is a past-the-end iterator. It points to nothing;
it points beyond the last element of x.]
So how can you assign s to x? Several ways.
(1) The simplest: assignment.
x.assign(s.begin(), s.end());
This will work regardless of whether s is empty or nonempty.
(In principle this is the simplest method, but it will only work
if your compiler supports member templates. I think that the only
compilers that support member templates at this point are ones
that use the Edison Design Group front end.)
(2) Insert s's elements.
x.insert(x.begin(), s.begin(), s.end());
If x is initially empty, then, after this function call, it will
be equal to s. Unfortunately, this, too, relies on member templates.
(3) Assignment through an insert iterator.
copy(s.begin(), s.end(), back_inserter(x));
This is more or less equivalent to method (2), although less efficient.
Method (3), though, has the virtue that it will work on compilers
that don't support member templates.
(4) Set x to the right size, and then use copy.
x.resize(s.size());
copy(s.begin(), s.end(), x.begin());
I'm crossposting to comp.lang.c++.moderated, and directing followups
to that group, because this is really more about techniques of using
the STL than about what the standard says.
---
[ 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
]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: aGriffiths@ma.ccngroup.com (Alan Griffiths)
Date: 1997/03/21 Raw View
In article: <3332AA13.7BC8@interpow.net> Barry Fortune <joburg@interpow.net> writes:
>
> I have just switched to Microsoft VC++ ver 5.0 and have come across the
> following problem with a
> vector.
>
> 1. I construct a vector with default constructor eg
> vector<char> x;
> 2. I invoke a copy algorithm eg
> string s = "abc";
> copy(s.begin(), s.end(), x.end());
A better idea is:
copy(s.begin(), s.end(), back_inserter(x));
> What happens is that the default constructor for vector does no
> allocation - just set pointers to nulls.
> (PJ Plauger's code is used by this implementation).
> Then x.end() is a null pointer, so the copy tries to dereference a null
> pointer and an exception is thrown.
That's reasonable :)
> Is this the correct behaviour for the default constructor to vector - or
> is it supposed to be ready to
> handle an immediate copy.
The copy algorithm does not extented the target (but an iterator
adaptor can - as above). Copy works in the same way as e.g. memcpy() -
it assumes that the target is valid.
__
Alan Griffiths | Work : agriffiths@ma.ccngroup.com
Senior Systems Consultant, | Tel. : +44 115 934 4517
CCN Group Limited. | Home : alan@octopull.demon.co.uk
(ACCU C++ SIG organiser) | (ACCU: http://bach.cis.temple.edu/accu)
---
[ 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: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1997/03/25 Raw View
Barry Fortune writes:
> I have just switched to Microsoft VC++ ver 5.0 and have come across the
> following problem with a
> vector.
> 1. I construct a vector with default constructor eg
> vector<char> x;
> 2. I invoke a copy algorithm eg
> string s = "abc";
> copy(s.begin(), s.end(), x.end());
> What happens is that the default constructor for vector does no
> allocation - just set pointers to nulls.
> (PJ Plauger's code is used by this implementation).
> Then x.end() is a null pointer, so the copy tries to dereference a null
> pointer and an exception is thrown.
> Is this the correct behaviour for the default constructor to vector - or
> is it supposed to be ready to
> handle an immediate copy.
The default constructor of vector does not allocate anything. If you
provide an element count as initializer, it will create that many
objects in the vector using the default constructor (or any value you
provide as the second argument of the vector constructor):
vector<char> x(5, ' '); // 5 whitespaces
You you intend to insert elements into the vector, you must use an
inserter iterator, using one of the following alternatives:
copy(s.begin(), s.end(), back_inserter(x));
// or
copy(s.begin(), s.end(), inserter(x, x.end()));
--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br mailto:aoliva@acm.org
Universidade Estadual de Campinas, SP, Brasil
---
[ 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 ]