|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2002-03-08 12:23:08
On Friday, March 8, 2002, at 11:16 AM, David Abrahams wrote:
>> Sorry to be dense, but what vector invariant is broken?
>
> Oh, for example, that the vector can be copied or destroyed or the 0th
> item can be dereferenced, depending on the definition of T and what you
> think uninitialized_flag actually does.
I agree that we would not want to break any of these invariants.
I feel that the uninitialized_flag option can be accomplished without
breaking these invariants. Perhaps the misunderstanding is in the
element:
For vector<T> to be able to use the uninitialized_flag constructor, T
must have a constructor that will execute in 0 instructions. If T has
such a constructor, then who is to say whether or not vector looped over
all of the addresses and executed this constructor or not?
Scalars have such a constructor. It is evident in code like:
void foo()
{
double x; // x is now in scope and constructed. No code has been
generated.
...
}
Here's another one:
void foo2()
{
double* vec = new double[10000];
// I now have an array of 10000 constructed doubles.
// Though these doubles are constructed, their value is indeterminant
}
I know that on some platforms some constructed but indeterminant scalars
can cause problems if loaded into certain machine registers. But that
does not seem to break vector invariants. And on many machines (the one
I'm typing on right now for example) even this is not a problem.
If you are on a platform where:
v[1] = v[0];
would cause a problem after a vector uninitialized constructor, then
don't do that! It is no different from saying don't do this:
double x, y;
x = y;
We don't need to mandate protection from such nonsense. The protection
is too expensive to mandate. However the protection is available (in
vector) for those who want it:
vector<double> v(10); // protected from uninitialized doubles
Meanwhile vector<double> v(10, uninitialized_flag) breaks no vector
invariants. The vector is destructible. The vector elements can be
assigned into. If your hardware doesn't mind (mine doesn't), you can
even assign from this uninitialized vector. I can't think of a reason
why you would want to do that though.
But even on hostile hardware such a vector can easily be made assignable
from and copyable by simply using memcpy instead of passing everything
through a floating point register. And I simply can not imagine a
platform where arbitrary bit patterns can not be moved via memcpy.
And if telling vector to "use" the zero instruction constructor for T is
still a problem, then how is that problem solved by passing the vector a
chunk of memory that has been "initialized" with these /same/ zero
instruction constructors? You've still got exactly the same vector!
Except with an added problem: the allocator may not be compatible with
the way the memory was allocated outside of the vector.
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk