Topic: std::vector constructors
Author: monkey@mninter.net ("Ken Durden")
Date: Sat, 9 Nov 2002 02:09:32 +0000 (UTC) Raw View
"Andy Sawyer" <andys@evo6.com.NoSpam> wrote in message
news:<fzufqqqu.fsf@ender.evo6.com>...
> In article <ush1her5c3ogf3@corp.supernews.com>,
> on Wed, 6 Nov 2002 03:08:48 +0000 (UTC),
> monkey@mninter.net ("Ken Durden") wrote:
>
> It would appear from this that the requirement on vector(size_type)
> would be to default-construct a single-element and then copy-construct
> N times, although the language is vague enough that either method
> seems reasonable. (In short, I'd be inclined not to rely on either set
> of semantics).
>
> Note that in some cases, N copies of a single default-constructed
> object might be more efficient that default-constructing N objects
> (reference-counting strings are an obvious example)
Thanks,
I'm a little disappointed the standard defaults to the vector(size_type, T
const & = T() ) version.
I've run into problems with it when my type T does not support copy
construction. On the occassions I've wanted to put these things into a
vector, I know up front how many elements I need and I never resize the
vector so there is no risk of vector doing internal copies.
As much as I have to use the example, given that its specifically prohibted
in the standard, it seems to me that the following should be legal.
template< typename T >
struct MyAutoPtr // like std::auto_ptr, but doesn't do assignment
{
MyAutoPtr( T * p = 0 ) : _p(p) {}
~MyAutoPtr() ( delete _p; );
T * _p;
private:
// No copy ctor or assignment op
MyAutoPtr & operator=( MyAutoPtr<T> const & );
MyAutoPtr( MyAutoPtr<T> const & );
};
int main()
{
std::vector< MyAutoPtr<int> > ptrVec( 10 );
ptrVec[0]._p = new int(2);
// not allowed, since MyAutoPtr doesn't, won't compile
// ptrVec.push_back( MyAutoPtr<int>( new int(7) );
// now allowed, same reason, won't compile
// ptrVec.resize( 20 );
}
Had the standard required the two different constructor forms then I could
be guaranteed that 10 default ctors would be called, and if someone knew (or
thought) that 1 default ctor, and 10 copy ctors would be faster than 10
default ctors then they could simply call the 2-arg version with T()
explicitly.
To workaround this issue, what I've done so far is add a copy constructor
for my classes which don't really support copy construction, but assert that
the data they own is empty (aka that I'm only copy ctor'ing a default
ctor'ed value).... but that kinda sucks :(
-ken
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Sat, 9 Nov 2002 07:11:57 +0000 (UTC) Raw View
In article <usoqcns9tkd67f@corp.supernews.com>,
on Sat, 9 Nov 2002 02:09:32 +0000 (UTC),
monkey@mninter.net ("Ken Durden") wrote:
> "Andy Sawyer" <andys@evo6.com.NoSpam> wrote in message
> news:<fzufqqqu.fsf@ender.evo6.com>...
>
> > It would appear from this that the requirement on
> > vector(size_type) would be to default-construct a single-element
> > and then copy-construct N times, although the language is vague
> > enough that either method seems reasonable. (In short, I'd be
> > inclined not to rely on either set of semantics).
>
> >
> > Note that in some cases, N copies of a single default-constructed
> > object might be more efficient that default-constructing N objects
> > (reference-counting strings are an obvious example)
>
> Thanks,
You are, as they say, welcome :-)
> I'm a little disappointed the standard defaults to the vector(size_type, T
> const & = T() ) version.
The standard doesn't "default" to anything, it _specifies_ that signature.
> I've run into problems with it when my type T does not support copy
> construction.
In which case, the behaviour of any std::container<T> is unspecified:
,----[ 23.1/para 3 ]
| The type of objects stored in these components must meet the
| requirements of CopyConstructible types (20.1.3), and the additional
| requirements of Assignable types.
`----
20.1.3 basically says, amongst other things the CopyConstructible
types must have copy constructors - this is (part of) the reason that
std::vector<std::auto_ptr<T> > doesn't work as some people expect it to.
> On the occassions I've wanted to put these things into a vector, I
> know up front how many elements I need and I never resize the vector
> so there is no risk of vector doing internal copies.
That's incorrect. containers are required to use their allocator to
construct the contained elements, and std::allocator<T>::construct is
required to invoke the copy constructor:
,----[ 20.4.1.1/para 12 ]
| void construct(pointer p, const_reference val);
|
| Returns: new((void *) p) T( val)
`----
> As much as I have to use the example, given that its specifically
> prohibted in the standard, it seems to me that the following should
> be legal.
[snip code]
No, it's clearly not valid, since your contained type is neither
CopyConstructible nor Assignable - and std::containers require the
contained type to be both.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sat, 9 Nov 2002 20:59:48 +0000 (UTC) Raw View
Andy Sawyer wrote:
> In article <usoqcns9tkd67f@corp.supernews.com>,
> on Sat, 9 Nov 2002 02:09:32 +0000 (UTC),
> monkey@mninter.net ("Ken Durden") wrote:
....
>>I'm a little disappointed the standard defaults to the vector(size_type, T
>>const & = T() ) version.
>
>
> The standard doesn't "default" to anything, it _specifies_ that signature.
I believe that what he's trying to say is that it specifies a signature
with a default value for the second argument; one he finds inconvenient
(in a context that, as you correctly point out, is illegal).
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sun, 10 Nov 2002 02:57:05 +0000 (UTC) Raw View
Andy Sawyer wrote:
> In article <usoqcns9tkd67f@corp.supernews.com>,
> on Sat, 9 Nov 2002 02:09:32 +0000 (UTC),
> monkey@mninter.net ("Ken Durden") wrote:
....
>>I'm a little disappointed the standard defaults to the vector(size_type, T
>>const & = T() ) version.
>
>
> The standard doesn't "default" to anything, it _specifies_ that signature.
I believe that what he's trying to say is that it specifies a signature
with a default value for the second argument; one he finds inconvenient
(in a context that, as you correctly point out, is illegal).
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: monkey@mninter.net ("Ken Durden")
Date: Wed, 6 Nov 2002 03:08:48 +0000 (UTC) Raw View
My STL platform provides the following constructor for std::vector
vector( size_type N, T const & t = T() );
Then, it does N copy-ctors calls from t to create the elements in the list.
Based on my reading of the Josuttis (my best reference since I dont own a
copy of the standard), this is incorrect, and the following 2 constructors
should be provided:
vector( size_type N ); // N default ctor calls
vector( size_type N, T const & t ); // N copy-ctor calls
a.) Am I correct on this point?
In the case of classes, it makes sense that every element be
default-constructed, and you get the same effect with the C-style equivalent
Obj * pObj = new Obj[10];
However, with primitives, should std::vector initialize all the elements to
T() or should they remain uninitialized? We've had this debate at work a few
times now from people who don't want to switch to std::vector because
they're concerned about performance impact.
int * prInt = new int[10]; // 10 uninitialized int values
std::vector<int> v( 10, 0 ); // 10 int's initialized to 0
std::vector<int> v( 10 ); // 10 unitialized int's, or 10 int's
initialized to 0??
As I said, on my platform (VC6) these two statements are equivalent, but I'd
like to know what the standard says about it.
Thanks,
-ken
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Andy Sawyer <andys@evo6.com.NoSpam>
Date: Tue, 5 Nov 2002 22:24:28 CST Raw View
In article <ush1her5c3ogf3@corp.supernews.com>,
on Wed, 6 Nov 2002 03:08:48 +0000 (UTC),
monkey@mninter.net ("Ken Durden") wrote:
> My STL platform provides the following constructor for std::vector
>
> vector( size_type N, T const & t = T() );
>
> Then, it does N copy-ctors calls from t to create the elements in the list.
>
> Based on my reading of the Josuttis (my best reference since I dont own a
> copy of the standard), this is incorrect, and the following 2 constructors
> should be provided:
>
> vector( size_type N ); // N default ctor calls
> vector( size_type N, T const & t ); // N copy-ctor calls
>
> a.) Am I correct on this point?
The standard (23.2.4.1) says that vector has the following constructor:
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
It also says (17.4.4.4) that an implementor may choose to implement
this as:
explicit vector( size_type n );
vector( size_type n, const T& value, const Allocator& );
The most detailed description I can find of the action of this
constructor is in 23.1.1, Table 67 which says:
X a(n, t); constructs a sequence with n copies of t.
It would appear from this that the requirement on vector(size_type)
would be to default-construct a single-element and then copy-construct
N times, although the language is vague enough that either method
seems reasonable. (In short, I'd be inclined not to rely on either set
of semantics).
Note that in some cases, N copies of a single default-constructed
object might be more efficient that default-constructing N objects
(reference-counting strings are an obvious example)
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Wed, 6 Nov 2002 21:03:29 +0000 (UTC) Raw View
Ken Durden wrote:
> My STL platform provides the following constructor for std::vector
>
> vector( size_type N, T const & t = T() );
That's precisely the signature specified by the standard, except for the
optional allocator argument at the end, which could have been split off
into another signature.
> Then, it does N copy-ctors calls from t to create the elements in the list.
>
> Based on my reading of the Josuttis (my best reference since I dont own a
> copy of the standard), this is incorrect, and the following 2 constructors
> should be provided:
>
> vector( size_type N ); // N default ctor calls
> vector( size_type N, T const & t ); // N copy-ctor calls
>
> a.) Am I correct on this point?
No.
> In the case of classes, it makes sense that every element be
> default-constructed, and you get the same effect with the C-style equivalent
>
> Obj * pObj = new Obj[10];
>
> However, with primitives, should std::vector initialize all the elements to
> T() or should they remain uninitialized? We've had this debate at work a few
It must initialize them with T(). The standard specifies that the
behavior of SequenceContainer(n,t) is to initialize the sequence with n
copies of t (table 67). The standard specifies that the default value of
t for std::vector<T> is T() (23.2.4).
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]