てきとーにスマートポインタを実装する

shared_ptrの仕組みが気になったので、てきとーに実装してみる。

#include <iostream>

using namespace std;

template <typename T> class Ptr {
  T *p;
  int *cnt;
public:
  Ptr(T *p) : p(p) {
    cnt = new int(1);
    cout << "count=" << *cnt << endl;
  }

  Ptr(const Ptr<T> &self) {
    p = self.p;
    cnt = self.cnt;
    (*cnt)++;
    cout << "count=" << *cnt << endl;
  }

  ~Ptr() {
   (*cnt)--;
   cout << "count=" << *cnt << endl;

    if (*cnt < 1) {
      delete p;
      delete cnt;
      cout << "delete!" << endl;
    }
  }

  T *ptr() { return p; }
};

template <typename T>
Ptr<T> foo(T *p) {
  cout << "in foo()" << endl;
  Ptr<T> ptr = Ptr<T>(p);
  cout << "out foo()" << endl;
  return ptr;
}

int main() {
  {
    cout << "in loop1" << endl;
    Ptr<int> p1 = foo<int>(new int(100));
    cout << *p1.ptr() << endl;

    {
      cout << "in loop2" << endl;
      Ptr<int> p2 = p1;
      cout << *p2.ptr() << endl;
      cout << "out loop2" << endl;
    }

    cout << "out loop1" << endl;
  }

  return 0;
}


in loop1
in foo()
count=1
out foo()
count=2
count=1
100
in loop2
count=2
100
out loop2
count=1
out loop1
count=0
delete!
cntをポインタじゃなくすると、コピーコンストラクタでうまくコンパイルできなかった。う゛ーん


C++のソースを見るたびに、クラス(構造体)のコピーが気になってたけど、コピーコンストラクタとか代入演算子のオーバーロードがあるから、わりとふつーなのかな…