簡単なshared_ptrを実装してみた
なんか流行ってるらしいし、久しぶりにC++な趣味のコーディングしたかったので、一部機能を省いた簡単なshared_ptrを実装してみた(もちろんスレッドアンセーフ)。shared_ptrの挙動って確かこんなんだっけ……。
shared_ptr.h
#ifndef _YUYARIN_SHARED_PTR_H #define _YUYARIN_SHARED_PTR_H namespace yuyarin { template<typename Tp> class ref_count { public: // default constructor ref_count(void) : m_ptr(NULL), m_count(0) { } // normal constructor ref_count(Tp* ptr) : m_ptr(ptr), m_count(1) { } // destructor ~ref_count(void) { delete m_ptr; } // add reference: count up void add(void) { m_count++; } // release reference: count down and if count is 0, then delete oneself. void release(void) { m_count--; if(m_count==0) { delete this; } } // for debug unsigned int refcount(void) { return m_count; } private: Tp* m_ptr; unsigned int m_count; }; // end of class ref_count template<typename Tp> class shared_ptr { public: // default constructor shared_ptr(void) : m_ptr(NULL), m_pref_count(NULL) { } // normal constructor explicit shared_ptr(Tp* ptr) : m_ptr(ptr), m_pref_count(NULL) { m_pref_count = new ref_count<Tp>(ptr); } // copy constructor shared_ptr(const shared_ptr<Tp> &sp) : m_ptr(sp.m_ptr) { sp.m_pref_count->add(); m_pref_count = sp.m_pref_count; } // destructor ~shared_ptr() { m_pref_count->release(); } // assignment shared_ptr& operator=(const shared_ptr &sp) { if(m_pref_count!=NULL) { m_pref_count->release(); } if(sp.m_pref_count!=NULL) { sp.m_pref_count->add(); } m_ptr = sp.m_ptr; m_pref_count = sp.m_pref_count; return *this; } // get reference(not allowed NULL pointer) Tp& operator*() const { if(m_ptr==0) { //error } return *m_ptr; } // get pointer(not allowed NULL pointer) Tp* operator->() const { if(m_ptr==0) { //error } return m_ptr; } // get pointer Tp* get() const { return m_ptr; } // for debug unsigned int refcount(void) { return m_pref_count->refcount(); } private: Tp* m_ptr; ref_count<Tp>* m_pref_count; }; // end of class shared_ptr } // end of namespace yuyarin #endif // !_YUYARIN_SHARED_PTR_H
shared_ptr_test.cpp
#include <iostream> #include "shared_ptr.h" class TestObject { public: TestObject(void) { std::cout << "construct " << this << std::endl; } ~TestObject(void) { std::cout << "destruct " << this << std::endl; } void greet(void) { std::cout << "Hello!! I'm " << this << std::endl; } }; typedef yuyarin::shared_ptr<TestObject> p; template<typename T> void print(T s) { std::cout << s << std::endl; } void func(p ptrX) { p ptrY = ptrX; print(ptrX.refcount()); print(ptrY.refcount()); } int main(void) { { p ptr1(new TestObject());//construct print(ptr1.refcount());//1 ptr1->greet(); ptr1.get()->greet(); (*ptr1).greet(); p ptr2 = ptr1; print(ptr1.refcount());//2 print(ptr2.refcount());//2 // scope print("enter a scope"); { p ptr3 = ptr1; print(ptr1.refcount());//3 print(ptr2.refcount());//3 print(ptr3.refcount());//3 ptr1 = ptr3; print(ptr1.refcount());//3 print(ptr2.refcount());//3 print(ptr3.refcount());//3 } print("left the scope"); print(ptr1.refcount());//2 print(ptr2.refcount());//2 print("enter a function"); func(ptr1); // 4 // 4 print("left the function"); print(ptr1.refcount());//2 p ptr4(new TestObject());//construct ptr2 = ptr4; print(ptr1.refcount());//1 print(ptr2.refcount());//2 print(ptr4.refcount());//2 p ptr5(new TestObject());//construct ptr5 = ptr1;// destruct print(ptr1.refcount());//2 print(ptr5.refcount());//2 // destruct // destruct } print("out of scope"); }
result
construct 00931B10 1 Hello!! I'm 00931B10 Hello!! I'm 00931B10 Hello!! I'm 00931B10 2 2 enter a scope 3 3 3 3 3 3 left the scope 2 2 enter a function 4 4 left the function 2 construct 00931B48 1 2 2 construct 00931B68 destruct 00931B68 2 2 destruct 00931B48 destruct 00931B10 out of scope
なんだかんだで一時間以上かけてしまった……。