DATAKIT API  V2025.1
How to use Smart Pointers

Dtk_SmartPtr vs C/C++ pointers








From the user's point of view, a smart pointer is similar to a typedef used to mask a C/C++ Pointer:

/* C/C++ Pointer*/
Dtk_Foo *obj;
obj = new Dtk_Foo();
obj->doSomeThing();
/* typedef Dtk_Foo * Dtk_FooPtr; */
Dtk_FooPtr objP;
objP = Dtk_Foo::Create();
objP->doSomeThing();


Smart Pointers encapsulate C/C++ Pointer to protect pointer from address and/or data corruption.
Here a list of the advantages:

  • Smart Pointer is initialized by default to NULL. So unpredictable behaviour is avoided.
  • We can't increase or decrease the Smart Pointer. So no corruption can appear.
  • Programer doesn't need to free memory. Smart pointer automatically frees itself. There isn't any Memory Leak by this way.
    Let's see a comparison between C/C++ Pointers and Smart Pointers:

    #ifdef C_POINTERS
    void function()
    {
    Dtk_Symbol *c1, *c2; // uninitialized pointers
    c1 = AnyFunctionThatReturnsDtk_SymbolPointer(); // OK
    ++c1; // disaster
    c1 = 0x00000F; // ......
    AnyFunctionThatTakesTwoDtk_SymbolParameters(c1, c2); // c2 still uninitialized; unpredictable result!
    delete c1; // c1 freed "outside" the API control
    c1->AnyFunction(); // c1 is still deleted but not set to NULL => unpredictable result!
    }
    #else // SMART POINTERS
    void function()
    {
    Dtk_SymbolPtr c1, c2; // uninitialized pointers
    c1 = AnyFunctionThatReturnsDtk_SymbolSmartPointer(); // OK
    //++c1; // compilation error!
    //c1 = 0x00000F; // compilation error!
    AnyFunctionThatTakesTwoDtk_SymbolPtrParameters(c1, c2); // the function traps c2 == 0 and returns an error
    //delete c1; // compilation error! It's not a pointer !!!
    c2->AnyFunction(); //c2 is set to NULL => An exception is thrown
    c2 = c1; //we copy the c1 pointer into c2 and the pointed object is notified it is referred by two pointers now
    c1->AnyFunction(); // c1 is not deleted
    // when both c1 and c2 go out of scope, the pointed object receives
    // a notification, and garbage collection can take place
    }



Dtk_SmartPtr Typedef

Dtk_SmartPtr is a template class.
So it should be used with Dtk_SmartPtr<XXX> with XXX the encapsulated class.
However, DATAKIT Library provide typedef to make SmartPtr Handling easier.
The typedef is created in this way:

typedef Dtk_SmartPtr< XXX > XXXPtr

where XXX is the encapsulated class.

void function()
{
Dtk_SmartPtr< Dtk_Symbol > SymbPtr1; //This is the default use - without typedef -
Dtk_SymbolPtr SymbPtr2; //This is the typedef use
SymbPtr1 = Dtk_Symbol::Create();
SymbPtr2 = SymbPtr1;
//...
}



How To Create Dtk_SmartPtr

All classes that can be handled with DtkSmartPtr have 'Create' methods. Theses methods are like constructors (new) but they return a DtkSmartPtr to the Object. NB: For almost classes. It's not possible to create static objects or dynamic objects with the new operator.

void function()
{
Dtk_SymbolPtr SymbPtr;
SymbPtr = Dtk_Symbol::Create();
//Dtk_Symbol StaticSymbol; //Compilation Error : Constructor is not available !
Dtk_Symbol * CSymbolPtr;
//CSymabolPtr = new Dtk_symbol(); //Compilation Error.
//...
}



Tests on Dtk_SmartPtr

The Dtk_SmartPtr classes provide methods for user-defined conversion, to make the usual C/C++ pointer tests possible:

void function(Dtk_SymbolPtr inSymbol)
{
if(inSymbol) // as for a C/C++ pointer! WARNING this method is deprecated and will be removed in the V64 release.
{
//....
}
if(inSymbol.IsNotNULL()) //this is the same test
{
//...
}
}



Dtk_SmartPtr Duplication

In some cases, we need to duplicate data to keep track of the main entity.
The Dtk_SmartPtr classes provide methods to clone objects:

void function(Dtk_SymbolPtr inSymbol)
{
Dtk_SymbolPtr Symbol2;
inSymbol.clone(Symbol2); // we clone inSymbol into Symbol2. It results in distinct pointers.
//...
}



Dtk_SmartPtr Promotion

Consider an API class XXX (for Example Dtk_symbol) derived from an API class YYY (for example Dtk_2dEntity).
The Dtk_SmartPtr class XXXPtr provides a static method to "promote" a Dtk_SmartPtr YYYPtr to a Dtk_SmartPtr XXXP (or vice versa).
if class XXX is not derived from class YYY. Promoting the YYYPtr to YYYPtr (or vice versa) will result in a NULL YYYPtr.

Dtk_status Write2dEntity(Dtk_2dEntityPtr& in2dEntity)
{
if( in2dEntity.IsNotNULL() )
return DTK_ISERROR;
switch( in2dEntity->get_type_detk() )
{
{
//OK a Dtk_2dEntityPtr can be promoted to Dtk_SymbolPtr because
//the get_type_detk() method informs that it's a symbol (Mother Class To Child Class)
//OK a Dtk_Symbol can be promoted to Dtk_2dEntity (Child Class To Mother Class)
WriteSymbol(Symbol);
//Error !!! A Dtk_Symbol can't be promoted to a Dtk_Dimension (Sister Class)
// => the promotion will result into a NULL pointer
//Error !!! Entity2d could be promoted to a Dtk_DimensionPtr (Mother Class To Child Class)
//but it's a symbol !!! => the promotion will result into a NULL pointer
break;
}
default:
{
//...
}
}
}



How to Delete Dtk_SmartPtr

In theory, you don't have to delete a Dtk_SmartPtr because it will be automatically deleted. However, if you want to manually delete a Dtk_SmartPtr you just have to affect a NULL pointer.

Dtk_status AnyFunction()
{
Dtk_SymbolPtr SymbPtr;
SymbPtr = Dtk_Symbol::Create(); //we create the SymbPtr smart pointer
Dtk_SymbolPtr SymbPtr2, SymbPtr3;
SymbPtr2 = Dtk_Symbol::Create(); //we create the SymbPtr2 smart pointer
SymbPtr3 = SymbPtr2; //now the pointer of SymbPtr2 is referenced twice.
//... some code
SymbPtr = NULL; //such SymbPtr is referenced only once. It will be deleted
SymbPtr2 = NULL; //such SymbPtr2 is referenced twice the counter is decreased and the object pointed by SymbPtr2
// is not deleted because is referenced by SymbPtr3
return DTK_NOERROR; //end of scope SymbPtr3 is automatically deleted.
//The object pointed is not referenced. So it is deleted also.
}
Dtk_SmartPtr::IsNotNULL
Dtk_bool IsNotNULL() const
Definition: util_ptr_dtk.hpp:119
Dtk_Symbol
This is the general symbol class. It's basically composed of Dtk_CompositeText and geometrical elemen...
Definition: util_draw_dtk.hpp:6505
Dtk_status
Definition: dtk_status.hpp:16
DTK_TYPE_SYMBOL
@ DTK_TYPE_SYMBOL
Definition: define.h:409
Dtk_Symbol::Create
static Dtk_SymbolPtr Create()
Base constructor.
DTK_ISERROR
@ DTK_ISERROR
Definition: dtk_status.hpp:9
Dtk_SmartPtr::DtkDynamicCast
static Dtk_SmartPtr< T > DtkDynamicCast(const Dtk_SmartPtr< T2 > &p)
Definition: util_ptr_dtk.hpp:101
Dtk_SmartPtr
Definition: util_ptr_dtk.hpp:37
DTK_NOERROR
@ DTK_NOERROR
Definition: dtk_status.hpp:10