|
Boost Users : |
From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-12-12 10:28:57
On Wednesday 12 December 2001 03:49 am, you wrote:
> I think it is possible to be more specific about the kind (can't use the
> word class here)
> of class I intend to represent by volatile.
> It contains only values by member, and pointers to memory which it has
> allocated
> on construction or in an explicit "init (or open, or allocate)" type of
> call, which are explicitly freed in its destructor,
> or in an explicit "destroy (or close, or free)" type of call.
> It has only the default copy operator.
There's a big difference between these two: if they allocate in the
constructor and deallocate in the destructor, but don't copy the resources
then there is a serious design flaw here. The fix is not to change
std::vector, but to either:
1) Make the copy constructor/copy assignment operator do the right thing
2) Make the class explicitly noncopyable (pass pointers around instead)
3) Make the class a lightweight "handle" (basically a boost::shared_ptr) to
the actual resources allocated.
All cases allow some form of usage in std::vector; 1 & 3 allow direct usage,
whereas 2 requires that the object be explicitly allocated. All cases also
avoid the ability to shoot oneself in the foot, and don't require changes to
std::vector.
> A struct with no member functions, which contains pointers to allocated
> memory, and for which
> there exist helper functions to allocate and delete the memory
> associated with the pointers, fits
> this description, and is exactly what is found in a lot C style
> programming.
... and there is no reason why such a class would not be safely
CopyConstructable. Something like this is already usable in std::vector, you
just have to deal with allocation/deallocation on your own.
> I think that being able to use STL in a shop full of C style programs
> and programmers is a good thing.
Perhaps.
> It lowers the threshold for entry into the STL and C++ style of
> programming.
I disagree with this completely. If a programmer new to C++ has to deal with
objects whose destructors should not be called, they _will_ be confused. One
of the basic tenets of C++ is that destructors will be called on all
deallocated objects.
> Vector resizing is not impossible for such a structure.
> How to:
> Default copy is made (exactly copy of values
> and pointers) and no destructor is called afterwards.
>
> That's what I meant when I said "destructor should not be called after
> copy operation".
Again, one has to essentially subvert the C++ type system to make this
possible, and break with C++ traditions. A class type that requires this
behavior can't be passed as an argument to a function, or can't be returned
(unless the return-value optimization is supported: do you really want your
object's behavior to differ depending on a legal optimization?)
> Does SGI or Boost have a trait assigned for all predefined types?
boost::is_fundamental<T>::value
> >I'd be happy to see this type of object go gently into that good night.
> > I'm a big fan of the "a type must be either CopyConstructable or
> > Noncopyable." If my name was Scott Meyers, I'd put that in a book :)
>
> I think that is the correct conclusion ... given infinte dealines and a
> universal desire to adopt STL programming
> in a single gulp. Only if we live in a less than ideal world is there
> any reason to do otherwise.
It's not really an STL issue, however. If we're going from C, which has no
notion of construction or destruction, to C++, which has both construction
and automatic destruction, we need to watch out for "half-breeds." The kinds
of types we were talking about earlier, where the constructor allocates,
destructor deallocates, but the copy constructor doesn't copy fall into this
category. They aren't C structures, because they have constructors; however,
they aren't safe C++ classes, because they can easily be used in ways that
will break.
Wouldn't it take longer for programmers not familiar with C++ semantics to
figure out why they can't now pass these structures as arguments that it
would just to fix the structures themselves? One quick fix: make all of the
raw pointers into boost::shared_ptrs. Then the default copy constructor/copy
assignment operator will handle reference-counting automatically.
Doug
Doug
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net