Boost logo

Boost :

From: Igor Smirnov (Igor.Smirnov_at_[hidden])
Date: 2001-06-13 14:03:54


Hello,

      Let me join your discussion about smart pointers. I discovered your
news group only yesterday. During one day I received a few e-mails about
smart pointers from your news group. So you please excuse me if I write
something which has already been discussed a hundred times. During my
work with C++ I came to totally different attitude toward automation of
pointers with respect to what I see in this "boost" web-page and I would
like to express my opinion. I'll try to write shorter.

There is a lot of different variants of pointers. It is impossible and
senseless to include all of them. It needs to choose a few base types
which meet all or almost all needs. For choosing one needs a criterion.
It is natural that it may be different criteria and they result in
different sets of base types.

By my opinion the most natural and useful criterion is conforming to the
object-oriented programming. This means that we need the pointers which
can be used as an instrument for establishing certain relationships
between objects. Mainly the relation of one object to another which may be
either of two different kinds: ownership or reference to alien object.
This relation should be steady and safe at the face of copying and
deleting, whenever these are deliberate or spontaneous actions. The
latter means that the correct behavior should be provided by default. Of
course, the first and the second type of pointers should behave
differently.

Note, that this goal is generally not compatible with performance or speed
of computing. If you choose the maximal performance, you should perhaps
come to something you have already described at the boost www-page about
smart pointers. But this is not the consistent object-oriented approach.

Look, this is the first sentence from this page:

"Smart pointers are classes which store pointers to dynamically allocated
(heap) objects."

Is this crucial that they store pointers to heap objects. Indeed, the
automatic objects, local variables inside functions, are also dynamically
allocated in some sense, and hence they may disappear and crash the
program.

Generally this means that such smart pointer can not simulate reference to
alien or external object. The external object can be allocated not only
dynamically in free memory, but by any other way.

The next sentence from the same page:

"They behave much like built-in C++ pointers except that they
automatically delete the object pointed to at the appropriate time."

If the object is logically alien or external, it must not be deleted at
deletion of pointer, wherever the object is allocated. This again means
that you can not simulate the reference to such objects.

Your smart pointers can not simulate ownership as well. The template
shared_ptr, as well as std::auto_ptr, does not result in cloning the
object at copying the pointer. The pointer scoped_ptr is not copyable at
all.

The smart pointers of Andrei Alexandrescu may be called twice smart. It
seems that at appropriate parameters they can simulate ownership, but
perhaps they can never simulate the reference to alien object. Moreover,
the code is too large. At its permanent use the compilation time will be
extremal. Too many possibilities can confuse programmer and are not really
necessary.

If you are interested in more details about my approach, you can read a
text below the line, which is in fact the appendix to my preprint
available in total by address

http://weblib.cern.ch/format/showfull?uid=1622119_4396&base=CERCER&sysnb=2257993

But besides the appendix there is nothing more about the pointers in it.

Any comments are welcome. Thanks.

----------------------------------------------------------------------

               Safe use of pointers
               --------------------

The pointers play the principal role in object-oriented programming in
C++. Simultaneously they represent the most unreliable element of the
language. The manipulations with the pointers do not automatically force
adequate manipulations with addressed objects and vice versa. If the
pointer is used for establishing certain relations between objects, its
inertness can eventually corrupt the program. However, it turns out that
the logic of these relationships almost always falls into one of two
categories, and both of them may be determined and automated by the well
protected template and regular classes. Although the use of such classes
gives computer some additional work, it reduces time of programming,
provides certain scalability and re-use of the program, and, hence, seems
reasonable.

Shortly, the pointers support such relations between the objects when one
object can access or use another object but the latter is not the physical
or logical component of the first. Another application of the pointers is
the support of polymorphism, when one object accesses another one whose
type is not completely determined (we mean handling the derived types with
virtual functions; the term polymorphism is sometimes used for other
purposes, but here we use the meaning suggested in [B. Stroustrup. The C++
programming language.]). What is missed is the support of polymorphism for
the logical components, although such relation occurs very frequently.

Moreover, even the supported relation, the reference to the alien object,
is not supported in total and prone to programming errors, since the
deletion of the addressed object does not result in annulling or clearing
the pointer and in denying the further access to it. The attempt to
simulate the relation of logical inclusion frequently leads to errors by
the same reason. In general, any regular pointer appearing as the class
member of an application class (except well debugged accessory library
classes) means a programming error, either now or in future. This makes
the result of computing random, depending on whether the hardware detects
``segmentation fault'' or what will be found at the place of the deleted
object.

This motivates substitution of the regular pointers, when they are used as
the class members, by the objects of template classes. Since we have only
two main types of relations: the reference to an alien object and the
logical inclusion, we need just two base templates simulating these
relations. As follows from the discussion above, the first one should
just mimic the regular pointer and protect it from the errors appearing at
careless manipulations with the addressed object. This type is called the
protected pointer and denoted by "ProtPtr<>". The addressed object should
know the addresses of all protected pointers to it and clear them at its
deletion. As an optional feature it can clear them at the substitution of
itself by another object through the operator of assignment. Technically,
the class of the addressed object should be derived from a special base
class called "RegProtPtr", "Register of Protected Pointers".

The second type should support the logical inclusion of one object into
another. If the pointer is copied or deleted either together with the
object to which it belongs or separately, this action should force similar
operation with the addressed object. By the other words, this pointer
should control the addressed object. Technically, such object should be
allocated in the free memory. To provide correct copying of the objects
of derived classes each such class should define the same virtual member
function "copy(void)" which merely allocates the new exemplar of the
object, a copy of itself, in the free memory. The controlling pointer is
denoted by "AutoCont<>".

The protected pointers do not have significant additional functionality
with respect to the regular pointers and perhaps they do not need special
notation in the class diagrams. The controlling pointers need a special
notation. They are marked by the open crossed box at the side of the
addressed object. Thus, if the connection is marked by the closed circle
at one end and by the closed box at the other end, this means that the
object of the class marked by the box is the member of the object of the
class marked by the circle. The same with the open box at the other end
means, that the object with the circle knows only the address of the
object with the box, but does not control it. The intermediate crossed
open box means that the addressed object is logically the member of the
object with the circle and is controlled by it. In the two latter cases
the actual type of the addressed object may be either that which is
denoted, or any derived from it.

-------------------------------------------------------------------

Regards
      Igor B. Smirnov


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk