Encore un pointeur intelligent, à compteur de référence, qui se comporte à l'utilisation comme un pointeur traditionnel. Attention, il n'est pas threadsafe.
Il a été fait en Builder C++ 2007.
Source / Exemple :
//******************************************************************************
//! @file TSmartPtr.h
//! @brief Gestion des pointeurs intelligents
//******************************************************************************
//******************************************************************************
// Version : 01
// Date : 11/2008
// Auteurs : Nirgal76 / Totoche76
// Description :
// - Création de la classe
//******************************************************************************
#ifndef _TSmartPtrH
#define _TSmartPtrH
//******************************************************************************
// MACROS
//******************************************************************************
#define SAFE_DELETE(p) { if (NULL!=p) { delete p; p=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if (NULL!=p) { delete[] p; p=NULL; } }
//******************************************************************************
// CONSTANTES
//******************************************************************************
const bool C_PTR_ARRAY = true; //!< Pointeur de base array
const bool C_PTR_SINGLE = false; //!< Pointeur de base simple
//******************************************************************************
//! @class TSmartPtr
//! @author Nirgal76
//! @author Totoche76
//! @date 11/2007
//! @brief Classe de gestion de pointeurs intelligents
//******************************************************************************
template <typename T, bool Array = C_PTR_SINGLE>
class TSmartPtr
{
//=====================================
// PUBLIC
//=====================================
public :
//------------------
// CYCLE DE VIE
//------------------
// Constructeurs
TSmartPtr();
// Constructeurs par copie
TSmartPtr(const TSmartPtr& rSmartPtr);
// Constructeurs à partir d'un pointeur c++
TSmartPtr(T* pPointer);
// destructeur
~TSmartPtr();
//------------------
// OPERATEURS
//------------------
// Opérations sur le pointeur
TSmartPtr& operator=(const TSmartPtr& rSmartPtr);
TSmartPtr& operator=(T* pPointer);
T& operator*();
T* operator->();
const T& operator*() const;
const T* operator->() const;
bool operator==(const TSmartPtr& rSmartPtr) const;
bool operator!=(const TSmartPtr& rSmartPtr) const;
operator T*(void) const;
//=====================================
// PRIVATE
//=====================================
private:
//------------------
// DONNEES
//------------------
int* mpRefCounter; //!< Nombre de référence sur le pointeur
T* mpPointer; //!< Pointeur de base
//------------------
// METHODES
//------------------
// Destruteur (par comptage de référence)
void Release();
}; // fin de TSmartPtr
//******************************************************************************
//! @brief Constructeur
//!
//! @param Aucun
//!
//! @return Aucun
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>::TSmartPtr()
{
mpRefCounter=NULL;
mpPointer=NULL;
}// fin du constructeur
//******************************************************************************
//! @brief Constructeur par copie
//!
//! @param rSmartPtr : pointeur intelligent à copier
//!
//! @return Aucun
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>::TSmartPtr(const TSmartPtr<T, Array>& rSmartPtr)
{
mpPointer = rSmartPtr.mpPointer;
mpRefCounter = rSmartPtr.mpRefCounter;
if (NULL!=mpRefCounter)
++(*mpRefCounter);
}// fin du constructeur par copie d'un pointeur intelligent
//******************************************************************************
//! @brief Constructeur par copie d'un pointeur de base
//!
//! @param pPointer : pointeur de base à copier
//!
//! @return Aucun
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>::TSmartPtr(T* pPointer)
{
mpPointer=pPointer;
if (NULL==mpPointer)
mpRefCounter = NULL;
else
mpRefCounter = new int(1);
}// fin du constructeur
//******************************************************************************
//! @brief Destructeur
//!
//! @param Aucun
//!
//! @return Aucun
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>::~TSmartPtr()
{
Release();
}// fin du destructeur
//******************************************************************************
//! @brief Opérateur d'affectation (=)
//!
//! @param rSmartPtr : pointeur intelligent source
//!
//! @return Le pointeur
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>& TSmartPtr<T, Array>::operator=(const TSmartPtr<T, Array>& rSmartPtr)
{
Release();
mpPointer = rSmartPtr.mpPointer;
mpRefCounter = rSmartPtr.mpRefCounter;
if (NULL!=mpRefCounter)
++(*mpRefCounter);
return *this;
}// fin de l'opérateur d'affectation
//******************************************************************************
//! @brief Opérateur d'affectation (=)
//!
//! @param pPointer : Pointeur de base
//!
//! @return Le pointeur
//******************************************************************************
template <typename T, bool Array>
inline TSmartPtr<T, Array>& TSmartPtr<T, Array>::operator=(T* pPointer)
{
Release();
mpPointer = pPointer;
if (NULL==mpPointer)
mpRefCounter = NULL;
else
mpRefCounter = new int(1);
return *this;
}// fin de l'opérateur d'affectation
//******************************************************************************
//! @brief Opérateur d'égalité (==)
//!
//! @param rSmartPtr : pointeur intelligent à comparer
//!
//! @return true si les pointeurs sont égaux
//******************************************************************************
template <typename T, bool Array>
inline bool TSmartPtr<T, Array>::operator==(const TSmartPtr<T, Array>& rSmartPtr) const
{
return mpPointer == rSmartPtr.mpPointer;
}// fin de l'opérateur d'égalité
//******************************************************************************
//! @brief Opérateur de non égalité (!=)
//!
//! @param rSmartPtr : pointeur intelligent à comparer
//!
//! @return true si les pointeurs sont différents
//******************************************************************************
template <typename T, bool Array>
inline bool TSmartPtr<T, Array>::operator!=(const TSmartPtr<T, Array>& rSmartPtr) const
{
return mpPointer != rSmartPtr.mpPointer;
}// fin de l'opérateur de non égalité
//******************************************************************************
//! @brief Renvoi la valeur du pointeur (opérateur *)
//!
//! @param Aucun
//!
//! @return Valeur du pointeur
//******************************************************************************
template <typename T, bool Array>
inline T& TSmartPtr<T, Array>::operator*()
{
return *mpPointer;
}// fin de l'opérateur de valeur
//******************************************************************************
//! @brief Renvoi la référence du pointeur (opérateur ->)
//!
//! @param Aucun
//!
//! @return Référence du pointeur
//******************************************************************************
template <typename T, bool Array>
inline T* TSmartPtr<T, Array>::operator->()
{
return mpPointer;
}// fin de l'opérateur de référence
//******************************************************************************
//! @brief Renvoi la référence du pointeur (opérateur *) en const
//!
//! @param Aucun
//!
//! @return Référence const du pointeur
//******************************************************************************
template <typename T, bool Array>
inline const T& TSmartPtr<T, Array>::operator*() const
{
return *mpPointer;
}// fin de l'opérateur de valeur
//******************************************************************************
//! @brief Renvoi la référence du pointeur (opérateur ->) en const
//!
//! @param Aucun
//!
//! @return Référence const du pointeur
//******************************************************************************
template <typename T, bool Array>
inline const T* TSmartPtr<T, Array>::operator->() const
{
return mpPointer;
}// fin de l'opérateur de référence
//******************************************************************************
//! @brief Casting sur le pointeur intelligent
//!
//! @param Aucun
//!
//! @return Pointeur de base
//******************************************************************************
template<typename T, bool Array>
inline TSmartPtr<T, Array>::operator T*(void) const
{
return mpPointer;
}// fin de l'opérateur de casting
//******************************************************************************
//! @brief Décrémente le compteur de référence et supprime le pointeur si = à 0
//!
//! @param Aucun
//!
//! @return Aucun
//******************************************************************************
template <typename T, bool Array>
inline void TSmartPtr<T, Array>::Release()
{
if (NULL!=mpRefCounter)
{
(*mpRefCounter)--;
if (*mpRefCounter <= 0)
{// compteur = 0 => destruction du pointeur
if (Array)
{// tableau de pointeur
SAFE_DELETE(mpRefCounter);
SAFE_DELETE_ARRAY(mpPointer);
}
else
{// pointeur
SAFE_DELETE(mpRefCounter);
SAFE_DELETE(mpPointer);
}
}// fin de compteur = 0
}
}// fin de Release
#endif
Conclusion :
Reste à le déclarer. Par exemple, pour déclarer un pointeur sur une classe TMaClasse :
TSmartPtr<TMaClasse> mpMaClasse;
mpMaClasse=new TMaClasse; // Instanciation de TMaClasse
mpMaClasse->Initialiser(); // Fonction membre de TMaClasse
...
Et ensuite, l'utiliser comme un pointeur traditionnel. sauf qu'il n'y a pas à le deleter bien entendu.
Si l'on veut vraiment le supprimer explicitement, lui affecter NULL.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.