Да, я думаю, что то, что я сделал сам, может быть даже лучше, чем shared_ptr
:
template<typename T>
class auto_
{
T *pValue;
mutable const auto_<T> *pPrev, *pNext;
public:
auto_() : pValue(new T()), pPrev(NULL), pNext(NULL) { }
auto_(T *pValue) : pValue(pValue), pPrev(NULL), pNext(NULL) { }
auto_(const T &v) : pValue(new T(v)), pPrev(NULL), pNext(NULL) { }
auto_(const auto_<T> &o) : pValue(o.pValue), pPrev(&o), pNext(NULL)
{ o.pNext = this; }
virtual ~auto_()
{
const auto_<T> *const pPrev = this->pPrev, *const pNext = this->pNext;
if (pPrev != NULL) { pPrev->pNext = pNext; }
if (pNext != NULL) { pNext->pPrev = pPrev; }
if (pPrev == NULL && pNext == NULL) { delete this->pValue; }
this->pPrev = this->pNext = NULL;
this->pValue = NULL;
}
auto_<T>& operator=(const auto_<T>& other)
{
if (this != &other)
{
this->~auto_();
this->pValue = other.pValue;
this->pPrev = &other;
this->pNext = other.pNext;
if (other.pNext != NULL) { other.pNext->pPrev = this; }
other.pNext = this;
}
return *this;
}
operator T&() { return *this->pValue; }
operator T*() { return this->pValue; }
T* operator->() { return this->pValue; }
T& operator *() { return *this->pValue; }
operator const T&() const { return *this->pValue; }
operator const T*() const { return this->pValue; }
const T* operator->() const { return this->pValue; }
const T& operator *() const { return *this->pValue; }
};
Пример использования:
template<typename T>
T recurse(T value, int depth)
{
if (depth > 0) { T result = recurse(value, depth - 1); return result; }
else { return value; }
}
auto_<int> test()
{
printf("Value: %d\n", *recurse(auto_<int>(10), 3));
auto_<int> p1 = recurse<auto_<int> >(5, 3);
printf("Value: %d\n", *p1);
auto_<int> p2 = 3;
p1 = p2;
p2 = p1;
return p2;
}
Это выглядит проще в использовании, чем shared_ptr
, ИМХО.
Есть ли у него какие-либо подводные камни, которые я пропустил (кроме очевидной небезопасности потока)?
Любая (конструктивная) критика приветствуется.