ich weiß nicht in wie weit Speicherverwaltung in C++ noch eine große Rolle spielt, gibt es mittlerweile ja zahlreiche Smart-Pointer Implementierungen sogar im C++-Standard durch boost.
Ich bin neulich auf eine Smart-Pointer Implementierung aus einem (älteren, nicht zu alt:), SuperSmartPointer nennen sie die Klasse) Buch gestoßen, welche auf einer globalen Referenzenzählung eines Types beruht. Ich habe dann die Referenzzählung von der eigentlichen Zeiger-Klasse entkoppelt und kann dadurch die Referenzen geerbter Klassen unter einer gemeinsamen Basissklasse zählen lassen und besitze dennoch die vollen Typ-Informationen im Zeiger. Leider jedoch nicht mehr in der Referenzimplementierung. Außerdem wird durch eine weitere kleine Modifikation in der Zeigerklasse zwischen statischen und dynamischen Variablen nicht direkt unterschieden (sie werden auch gezählt), was eine flexible Anwendung ermöglicht.
Ich dachte ich poste einfach Mal den Code, falls es jemanden anderen auch interessiert. Zyklische Abhängigkeiten und Parallelverarbeitung wird nicht unterstützt. Funktioniert in meiner bisherigen Anwendung wunderbar, so dass kein einziges manuelles delete mehr benutzt wird.
Also lange Rede kurzer Sinn, hier der Code:
(i) Die Referenzzähler-Implementierung:
Code: Alles auswählen
///// ref ///////////////////////////////////////////////////////////////////////////////
template <typename T>
class ref
{
protected:
static std::map<T*, unsigned int> rfrnc;
inline void init(T *);
inline void init(T &);
inline void finalize(T *);
public:
static std::map<T*, unsigned int> reference();
};
template <typename T> std::map<T*, unsigned int> ref<T>::rfrnc;
template<typename T>
void ref<T>::init(T *p)
{
if (rfrnc.find(p) == rfrnc.end())
rfrnc[p] = 1;
else
rfrnc[p]++;
}
template<typename T>
void ref<T>::init(T &p)
{
if (rfrnc.find(&p) == rfrnc.end())
rfrnc[&p] = 2;
else
rfrnc[&p]++;
}
template<typename T>
void ref<T>::finalize(T *p)
{
if(rfrnc.find(p) == rfrnc.end())
{
std::cerr << "ERROR: Missing entry in map!" << std::endl;
return;
}
unsigned int &r = rfrnc[p];
if(--r == 0)
{
rfrnc.erase(p);
delete p;
}
}
template <typename T>
std::map<T*, unsigned int> ref<T>::reference()
{
return rfrnc;
}
Code: Alles auswählen
///// ptr ///////////////////////////////////////////////////////////////////////////////
template <typename T, typename I = T>
class ptr : public ref<I>
{
T *p;
public:
ptr(T *);
ptr(const ptr<T, I> &);
ptr(T &);
~ptr();
ptr<T, I>& operator =(const ptr<T, I> &rhs);
const T& operator *() const;
const T* operator ->() const;
T& operator *();
T* operator ->();
operator void*() const { return p; }
};
template <typename T, typename I>
ptr<T, I>::ptr(T* p0)
{
init(p = p0);
}
template <typename T, typename I>
ptr<T, I>::ptr(T &p0)
{
p = &p0;
init(p0);
}
template <typename T, typename I>
ptr<T, I>::ptr(const ptr<T, I> &p0)
{
init(p = p0.p);
}
template <typename T, typename I>
ptr<T, I>::~ptr()
{
finalize(p);
}
template <typename T, typename I>
ptr<T, I>& ptr<T, I>::operator =(const ptr<T, I> &rhs)
{
if (this == &rhs)
return (*this);
finalize(p);
init(p = rhs.p);
return (*this);
}
template <typename T, typename I>
const T* ptr<T, I>::operator->() const
{
return (p);
}
template <typename T, typename I>
const T& ptr<T, I>::operator*() const
{
return (*p);
}
template <typename T, typename I>
T* ptr<T, I>::operator->()
{
return (p);
}
template <typename T, typename I>
T& ptr<T, I>::operator*()
{
return (*p);
}
(i) ptr<Type> p = ... (Referenz, Zeiger oder ptr<Type>)
(ii) ptr<Type, BaseType> p = ... (Referenz, Zeiger oder ptr<Type, BaseType>)
Funktioniert auch in stl-containern, z.B std::list<ptr<Type>> list. Allerdings habe ich das nur für die Liste bisher getestet.
Viele Grüße
Bergmon
p.s.: Werden keine Tabulatoren in der Formatierung unterstützt, oder ist es mein Fehler?