next up previous contents index
Next: Graph serialisation Up: pack/unpack Previous: pack/unpack   Contents   Index


Pointers

<rant>

Pointers are evil!. Pointers are a dangerous programming construction, and widely abused in the C++ programming world. They often lead to obscure programming errors, and in particular to memory leaks, which are notoriously hard to debug. If there is an alternative method that encapsulates pointers, or avoids their use altogether, then that should be used. Unfortunately, pointers are vital to programming in C, and many of the practices are imported into C++.

</rant>

Whilst the above might be considered a little extreme, it is worthwhile listing what pointers are used for, and considering what alternatives there might be. In Classdesc, objects are usually assumed to have the following properties: default constructable, copyable, assignable and serialisable. All the simple traditional C data types except for pointers satisfy these properties. Compound types (structs and classes) whose members satisy these properties also satisfy them, with classdesc automagically extending the serialisability property.

Pass by reference
In C++, the reference operator & makes obsolete the use of pointers for returning values from function subroutines, and improves type safety. Of course this use of pointers is of no concern for serialisation.
Dynamic Memory
In C++, we have the new operator to return an array of objects from the heap. However, one must be careful to delete the array of objects once finished with, otherwise a memory leak may result. In this case, encapsulation can help. If the pointer is encapsulated with a class definition, then the delete can be called automatically when the object's destructor is called, which happens automatically when an object goes out of scope. The simple case of allocating some dynamic memory from the heap can be most readily performed using the standard library container vector<T>.
Strings
char * variables can be replaced by the standard library string type.
Dynamic references
Dynamic references are used a lot to represent graph structures, or to provide access to objects declared outside the current scope. For some purposes, C++'s static reference type (T&) is suitable, but is limited to being initialised only at object construction time. Also, any reference loops will cause serialisation to enter an infinite loop and crash. C++ offers more possibilities in the form of ``smart pointers'', that guarantee destruction of the referenced object once the reference object goes out of scope. The standard C++ library provides auto_ptr, but this is noncopyable, pretty much defeating the purpose of smart pointers. The Boost library (http://www.boost.org) provides several different sharable smart pointers, that can be used. Classdesc provides its own concept, ref (see §2.3) that is a type of dynamic reference. It should be noted that linked lists can be handled easily with standard library containers.
Legacy APIs
Many C-based legacy APIs use pointers for pass by reference functionality, strings, or for anonymous references (to avoid publishing the full specification of an object). These APIs can be easily encapsulated to ensure any allocated pointers are appropriately cleaned up.
Global references
An object that needs to be destroyed before main() exits, yet needs to be referred to globally throughout the program cannot be implemented as a global object (which is destroyed after the program exits). Instead, it has to either be a global pointer, which is initialised when the object is created, or the entire program must be implemented as a method of an object which is created in main().
Runtime polymorphism
Since the actual datatype might vary, only references to the object can be handled. Traditional pointer-based polymorphic systems are not copyable, assignable nor serialisable, as copying a point to an allocated object invariably leads to double free() errors (in the case of destructors cleaning up pointers) or to memory leaks (in the case destructors don't do anything). Traditionally, copying is performed by means of a clone() virtual method, which is also how this is done in Java. EcoLab provides an PolyBase (see §2.7) base class in Poly.h which provides an interface for cloning, and interfaces for serialisation can be found in the PolyPack, PolyXML and PolyJson headers and a simple runtime type identification system. To create a reference, the smart, modern way to do this is via the shared_ptr smart pointer class, which is found in the TR1 library of your compiler, or in Boost if your compiler does not do TR1.


next up previous contents index
Next: Graph serialisation Up: pack/unpack Previous: pack/unpack   Contents   Index
Russell Standish 2016-09-02