fork download
  1. #include <iostream>
  2. #include <utility>
  3. #include <cassert>
  4.  
  5. template <class T>
  6. void default_delete(T *p)
  7. {
  8. delete p;
  9. }
  10.  
  11. template <class T>
  12. void default_array_delete(T *p)
  13. {
  14. delete [] p;
  15. }
  16.  
  17. template <class T>
  18. class shared_ptr
  19. {
  20. using pointer = T*;
  21. using reference = T&;
  22. using delete_fn = void (*) (pointer);
  23. using counter = int;
  24.  
  25. pointer ptr;
  26. counter *cnt;
  27. delete_fn del;
  28.  
  29. public:
  30. shared_ptr() noexcept
  31. : ptr(nullptr), cnt(nullptr), del( default_delete<T> )
  32. {
  33. std::cout << "shared_ptr()\n";
  34. }
  35.  
  36. explicit shared_ptr(pointer p) noexcept
  37. : ptr(p), cnt( new counter(1) ), del( default_delete<T> )
  38. {
  39. std::cout << "shared_ptr(pointer)\n";
  40. }
  41.  
  42. shared_ptr(pointer p, delete_fn d) noexcept
  43. : ptr(p), cnt( new counter(1) ), del(d)
  44. {
  45. std::cout << "shared_ptr(pointer, delete_fn)\n";
  46. }
  47.  
  48. shared_ptr(const shared_ptr &x) noexcept
  49. : shared_ptr(x.ptr, x.del)
  50. {
  51. cnt = x.cnt;
  52. ++*cnt;
  53. std::cout << "shared_ptr(const shared_ptr&)\n";
  54. }
  55.  
  56. shared_ptr(shared_ptr &&x)
  57. : ptr( std::move(x.ptr) ),
  58. cnt( std::move(x.cnt) ),
  59. del( std::move(x.del) )
  60. {
  61. std::cout << "shared_ptr(shared_ptr&&)\n";
  62. x.ptr = nullptr;
  63. x.cnt = nullptr;
  64. }
  65.  
  66. shared_ptr& operator = (const shared_ptr &x)
  67. {
  68. std::cout << "shared_ptr::operator=&\n";
  69. if (this != &x) {
  70. reset();
  71. ptr = x.ptr;
  72. cnt = x.cnt;
  73. del = x.del;
  74. ++*cnt;
  75. }
  76. return *this;
  77. }
  78.  
  79. shared_ptr& operator = (shared_ptr &&x)
  80. {
  81. std::cout << "shared_ptr::operator=&&\n";
  82. shared_ptr::swap(x);
  83. return *this;
  84. }
  85.  
  86. void swap(shared_ptr &x)
  87. {
  88. std::cout << "shared_ptr::swap(shared_ptr&)\n";
  89. std::swap(ptr, x.ptr);
  90. std::swap(cnt, x.cnt);
  91. std::swap(del, x.del);
  92. }
  93.  
  94. ~shared_ptr()
  95. {
  96. std::cout << "~shared_ptr::~shared_ptr()\n";
  97. if (cnt != nullptr && --*cnt == 0) {
  98. std::cout << " destroyed " << *ptr << "\n";
  99. del(ptr);
  100. delete cnt;
  101. }
  102. }
  103.  
  104. pointer operator -> () const noexcept
  105. {
  106. return ptr;
  107. }
  108.  
  109. reference operator * () const noexcept
  110. {
  111. return *ptr;
  112. }
  113.  
  114. pointer get() const noexcept
  115. {
  116. return ptr;
  117. }
  118.  
  119. explicit operator bool() const noexcept
  120. {
  121. return ptr != nullptr;
  122. }
  123.  
  124. bool unique() const noexcept
  125. {
  126. return use_count() == 1;
  127. }
  128.  
  129. counter use_count() const noexcept
  130. {
  131. return cnt != nullptr ? *cnt : 0;
  132. }
  133.  
  134. void reset()
  135. {
  136. this->~shared_ptr();
  137. ptr = nullptr;
  138. cnt = nullptr;
  139. }
  140.  
  141. void reset(pointer p)
  142. {
  143. reset();
  144. cnt = new counter(1);
  145. ptr = p;
  146. }
  147.  
  148. void reset(pointer p, delete_fn d)
  149. {
  150. reset();
  151. cnt = new counter(1);
  152. ptr = p;
  153. del = d;
  154. }
  155. };
  156.  
  157. template <class T, class... Args>
  158. shared_ptr<T> make_shared(Args&& ...args)
  159. {
  160. return shared_ptr<T>( new T( std::forward<Args>(args)... ) );
  161. }
  162.  
  163. int main()
  164. {
  165. shared_ptr<int> foo;
  166. shared_ptr<int> bar (new int(10));
  167.  
  168. foo = bar;
  169.  
  170. bar = make_shared<int> (20);
  171.  
  172. bar.reset();
  173. assert(!bar);
  174.  
  175. foo.reset(new int(30), default_delete);
  176. std::cout << *foo << std::endl;
  177. bar = foo;
  178. std::cout << bar.use_count() << std::endl;
  179. return 0;
  180. }
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
shared_ptr()
shared_ptr(pointer)
shared_ptr::operator=&
~shared_ptr::~shared_ptr()
shared_ptr(pointer)
shared_ptr::operator=&&
shared_ptr::swap(shared_ptr&)
~shared_ptr::~shared_ptr()
~shared_ptr::~shared_ptr()
 destroyed 20
~shared_ptr::~shared_ptr()
 destroyed 10
30
shared_ptr::operator=&
~shared_ptr::~shared_ptr()
2
~shared_ptr::~shared_ptr()
~shared_ptr::~shared_ptr()
 destroyed 30