]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Update the documentation of SmartPointer. 16233/head
authorWolfgang Bangerth <bangerth@colostate.edu>
Wed, 1 Nov 2023 18:08:56 +0000 (12:08 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Wed, 1 Nov 2023 23:33:02 +0000 (17:33 -0600)
include/deal.II/base/smartpointer.h

index 49dc336e7951af2deb8120837bc905b08b351511..f37d36eb127bdc737732e10b2dc648d44bf27b57 100644 (file)
 DEAL_II_NAMESPACE_OPEN
 
 /**
- * Smart pointers avoid using dangling pointers. They can be used just
- * like a pointer (i.e. using the <tt>*</tt> and <tt>-></tt> operators and
+ * The SmartPointer class avoids using dangling pointers. They can be used just
+ * like a pointer (i.e., using the <tt>*</tt> and <tt>-></tt> operators and
  * through casting) but make sure that the object pointed to is not deleted or
  * moved from in the course of use of the pointer by signaling the pointee its
  * use.
  *
- * Objects pointed to, i.e. the class T, should inherit Subscriptor or must
- * implement the same functionality. Null pointers are an exception from this
- * rule and are allowed, too.
+ * Conceptually, SmartPointer fills a gap between `std::unique_ptr` and
+ * `std::shared_ptr`. While the former makes it clear that there is a unique
+ * owner of an object (namely the scope in which the `std::unique_ptr` resides),
+ * it does not allow other places in a code base to point to the object. In
+ * contrast, `std::shared_ptr` allows many places to point to the same object,
+ * but none of them is the "owner" of the object: They all are, and the last
+ * one to stop pointing to the object is responsible for deleting it.
  *
- * The second template argument P only serves a single purpose: if a
- * constructor without a debug string is used, then the name of P is used as
- * the debug string.
+ * SmartPointer utilizes semantics in which one place owns an object and others
+ * can point to it. The owning place is responsible for destroying the object
+ * when it is no longer needed, and this will trigger an error if other places
+ * are still pointing to it via SmartPointer pointers. In other words, one
+ * should consider those places that hold a SmartPointer to an object as
+ * "observers", and an object may only be destroyed without an error if there
+ * are no observers left. With hindsight, perhaps a better name for the class
+ * would have been "ObserverPointer".
  *
- * SmartPointer does NOT implement any memory handling! Especially, deleting a
- * SmartPointer does not delete the object. Writing
- * @code
- * SmartPointer<T,P> dont_do_this = new T;
- * @endcode
- * is a sure way to program a memory leak! The secure version is
- * @code
- * T* p = new T;
- * {
- *   SmartPointer<T,P> t(p);
- *   ...
- * }
- * delete p;
- * @endcode
+ * To make this scheme work, SmartPointers need to increment the "observer
+ * count" when they point to an observed object. This is facilitated by
+ * requiring that the objects pointed to, i.e., the template type `T`, must
+ * inherit from the Subscriptor class.
  *
- * Note that a smart pointer can handle <tt>const</tt>ness of an object, i.e.
- * a <tt>SmartPointer<const ABC></tt> really behaves as if it were a pointer
- * to a constant object (disallowing write access when dereferenced), while
- * <tt>SmartPointer<ABC></tt> is a mutable pointer.
+ * In practice, using this scheme, if you try to destroy an object to which
+ * observers still point via SmartPointer objects, you will get an error that
+ * says that there are still observers of the object and that the object can
+ * consequently not be destroyed without creating "dangling" pointers. This
+ * is often not very helpful in finding where these pointers are. As a
+ * consequence, this class also provides two ways to annotate the observer
+ * count with information about what other places still observe an object.
+ * First, when initializing a SmartPointer object with the address of the
+ * object pointed to, you can also attach a string that describes the
+ * observing location, and this string will then be shown in error messages
+ * listing all remaining observers. Second, if no such string is provided,
+ * the name second template argument `P` is used as the debug string. This
+ * allows to encode the observer information in the type of the SmartPointer.
+ *
+ * @note Unlike `std::unique_ptr` and `std::shared_ptr`, SmartPointer does
+ *   NOT implement any memory handling. In particular, deleting a
+ *   SmartPointer does not delete the object because the semantics
+ *   of this class are that it only *observes* an object, but does not
+ *   take over ownership. As a consequence, this is a sure way of creating
+ *   a memory leak:
+ *   @code
+ *     SmartPointer<T> dont_do_this = new T;
+ *   @endcode
+ *   This is because here, no variable "owns" the object pointed to, and
+ *   the destruction of the `dont_do_this` pointer does not trigger the
+ *   release of the memory pointed to.
+ *
+ * @note This class correctly handles `const`-ness of an object, i.e.,
+ *   a `SmartPointer<const T>` really behaves as if it were a pointer
+ *   to a constant object (disallowing write access when dereferenced), while
+ *   `SmartPointer<T>` is a mutable pointer.
  *
  * @ingroup memory
  */

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.