Created
May 7, 2010 14:35
-
-
Save aragaer/393493 to your computer and use it in GitHub Desktop.
smart pointers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "sptest.h" | |
#include <stdio.h> | |
class test { | |
public: | |
test() { | |
printf("Test constructor\n"); | |
field = new char[20]; | |
is_deleted = false; | |
} | |
~test() { | |
printf("Test destructor\n"); | |
if (!is_deleted) // If you see the warning, something goes wrong | |
printf("Test was not cleaned up properly!\n"); | |
delete field; | |
} | |
void hello() { | |
printf("Hello, test\n"); | |
} | |
void del() { | |
is_deleted = true; | |
} | |
char *field; | |
bool is_deleted; | |
}; | |
typedef Csptr<test> sp_test; | |
template <> void Csptr<test>::Cwrap::Cleanup() { | |
if (!m_value) | |
return; | |
m_value->del(); | |
delete m_value; | |
} | |
// Typedef and cleanup using a macro. Should be expanded like this: | |
// typedef Csptr<int> spint; | |
// template <> void Csptr<int>::Cwrap::Cleanup() { | |
// // Nothing to do | |
// printf("Int smartptr cleanup!\n"); | |
// } | |
SMARTPTR_CLEANUP_BEGIN(spint, int) | |
// Nothing to do | |
printf("Int smartptr cleanup!\n"); | |
SMARTPTR_CLEANUP_END | |
template <> bool Csptr<int>::IsValid() { | |
printf("Something checks if the pointer is valid at all\n"); | |
return m_wrap != NULL; | |
} | |
test *make_test() { | |
return new test(); | |
} | |
sp_test make_sptest() { | |
return sp_test(*make_test()); | |
} | |
int a = 15; | |
int main(int argc, char *argv[]) { | |
sp_test spt(*make_test()); | |
Csptr<test> spt2; // Same as "sp_test spt2;" | |
sp_test spt3(make_sptest()); | |
Csptr<int> spint, spint2(a); | |
// Csptr<char> spchar; // Won't compile since there's no cleanup for char defined | |
spt->hello(); | |
spt2->hello(); | |
spt3->hello(); | |
printf("spt is %svalid\n", spt.IsValid() ? "" : "in"); | |
printf("spt2 is %svalid\n", spt2.IsValid() ? "" : "in"); | |
printf("spint is %svalid\n", spint.IsValid() ? "" : "in"); | |
printf("spint2 is %svalid\n", spint2.IsValid() ? "" : "in"); | |
spt3 = NULL; | |
spt3 = spt; | |
spt3.Unlink(); | |
spt2 = spt; | |
spt2->hello(); | |
printf("woof\n"); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
template <typename T> | |
class Csptr { | |
class Cwrap { // Internal wrapper for data, which counts references to itself | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Конструктор | |
////////////////////////////////////////////////////////////////////////// | |
Cwrap(T *value) : m_value(value), m_ref(0) { } | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Деструктор | |
////////////////////////////////////////////////////////////////////////// | |
~Cwrap() { } | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Увеличить счетчик ссылок | |
////////////////////////////////////////////////////////////////////////// | |
void AddRef() { | |
m_ref++; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Уменьшить счетчик ссылок | |
////////////////////////////////////////////////////////////////////////// | |
void Release() { | |
if (--m_ref == 0) { | |
Cleanup(); | |
delete this; | |
} | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Доступ к содержимому | |
////////////////////////////////////////////////////////////////////////// | |
T *value() { | |
return m_value; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Метод очистки хэндла. Должен быть определен для каждой специализации | |
////////////////////////////////////////////////////////////////////////// | |
virtual void Cleanup(); // Cleanup function. Must be defined for every used specialization | |
T *m_value; | |
int m_ref; | |
friend class Csptr; | |
}; | |
public: | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Пустой конструктор | |
////////////////////////////////////////////////////////////////////////// | |
Csptr() : m_wrap(NULL) {} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Конструктор копирования | |
////////////////////////////////////////////////////////////////////////// | |
Csptr(const Csptr &rval) { // Doesn't work without 'const' | |
m_wrap = rval.m_wrap; | |
m_wrap->AddRef(); | |
#ifdef _DEBUG | |
printf("Smart pointer created from copy\n"); | |
#endif | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Конструктор с инициализацией | |
////////////////////////////////////////////////////////////////////////// | |
Csptr(T &val) { | |
m_wrap = new Cwrap(&val); | |
m_wrap->AddRef(); | |
#ifdef _DEBUG | |
printf("Smart pointer created\n"); | |
#endif | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Деструктор | |
////////////////////////////////////////////////////////////////////////// | |
~Csptr() { | |
if (m_wrap) | |
m_wrap->Release(); | |
#ifdef _DEBUG | |
else | |
printf("Non-initialized "); | |
printf("Smart pointer destroyed\n"); | |
#endif | |
m_wrap = NULL; | |
} | |
///////////////////////////////////////////////////////////////////////// | |
/// @brief Разыменовать умный указатель. Для неинициализированных указателей вернет NULL | |
////////////////////////////////////////////////////////////////////////// | |
const T &operator * () const { | |
if (m_wrap == NULL) { | |
printf("Dereferencing null pointer!\n"); // Handle the error! | |
return NULL; | |
} | |
return *m_wrap->value(); | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Разыменовать умный указатель. Для неинициализированных указателей вернет NULL | |
////////////////////////////////////////////////////////////////////////// | |
T *const operator -> () const { | |
if (m_wrap == NULL) { | |
printf("Dereferencing null pointer!\n"); // Handle the error! | |
return NULL; | |
} | |
return m_wrap->value(); | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Оператор копирования умного указателя | |
////////////////////////////////////////////////////////////////////////// | |
Csptr &operator = (const Csptr &rval) { | |
if (m_wrap) | |
m_wrap->Release(); | |
m_wrap = rval.m_wrap; | |
m_wrap->AddRef(); | |
return *this; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Оператор копирования умного указателя из обычного | |
////////////////////////////////////////////////////////////////////////// | |
Csptr &operator = (T *rval) { | |
if (m_wrap) | |
m_wrap->Release(); | |
m_wrap = new Cwrap(rval); | |
m_wrap->AddRef(); | |
return *this; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief make the pointer invalid, removing reference to object | |
////////////////////////////////////////////////////////////////////////// | |
void Unlink() { | |
if (m_wrap) | |
m_wrap->Release(); | |
m_wrap = NULL; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Returns whether the smart pointer is valid | |
////////////////////////////////////////////////////////////////////////// | |
bool IsValid() { | |
return m_wrap != NULL; | |
} | |
protected: | |
Cwrap *m_wrap; | |
}; | |
// These macro definitions should wrap the cleanup definition. | |
// Wrapped value can be accessed as m_value | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Макрос начала объявления специализации умного указателя | |
////////////////////////////////////////////////////////////////////////// | |
#define SMARTPTR_CLEANUP_BEGIN(name, type) typedef Csptr<type> name; \ | |
template <> void Csptr<type>::Cwrap::Cleanup() { | |
////////////////////////////////////////////////////////////////////////// | |
/// @brief Макрос окончания объявления специализации умного указателя | |
////////////////////////////////////////////////////////////////////////// | |
#define SMARTPTR_CLEANUP_END } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment