shared_ptrを作る

C++のtemplateでBREW用にshared_ptrを書いてみた - 清水川Webをちらりとみて、短かったので勉強がてら読まずに実装してみた。いろいろ教えてもらいながら。

        • -

なおこれのコードを使おうとする人がいるといけないので改めて注意書きを書いておくと「勉強がてら」実装してみたコードをさらしているだけなので実用的に使うことは全く想定していません。というよりdeleteのところをfreeと書いて動かなかったりとかしながら作ったコードなので実用的な目的に使わないでください。

#include <iostream>
using namespace std;

template<typename T>
class PtrWrapper {
public:
  PtrWrapper(T* ptr):_ptr(ptr),_count(1){}
  ~PtrWrapper(){
    delete _ptr;
  }
  int dec(){
    _count--;
    cout << "obj " << *_ptr << " refcount " << _count << endl;
    return _count;
  }
  void inc(){
    _count++;
    cout << "obj " << *_ptr << " refcount " << _count << endl;
  }
  T* _ptr;
private:
  int _count;
};

template<typename T>
class SharedPtr {
public:
  SharedPtr(T* ptr):_ptrwrap(new PtrWrapper<T>(ptr)){
  }
  ~SharedPtr(){
    if(_ptrwrap->dec() == 0){
      delete _ptrwrap;
    };
  }
  T* operator->(){
    return _ptrwrap._ptr;
  }
  operator T*(){ // ここだけ文法が変?
    return _ptrwrap._ptr;
  }
  SharedPtr<T>& operator=(SharedPtr& rhs){ // 参照返しにしないとコピーが発生してしまう
    if(_ptrwrap->dec() == 0){
      delete _ptrwrap;
    };
    rhs._ptrwrap->inc();
    _ptrwrap = rhs._ptrwrap;
    return *this;
  }
  PtrWrapper<T> *_ptrwrap;
};

class MyValue {
public:
  MyValue():value(42){
    cout << "cstr wit 42" << endl;
  }
  MyValue(int v):value(v){
    cout << "cstr with value" << value << endl;
  }
  ~MyValue(){
    cout << "dstr" << value << endl;
  }
  MyValue(const MyValue &v){
    cout << "copy cstr " << value << endl;
    value = v.value;
  }
  int value;
};

ostream& operator<<(std::ostream& os, const MyValue& v){
  os << v.value;
  return os;
}

typedef SharedPtr<MyValue> SPM;

int main(){
  {
    SPM x(new MyValue(43));
    {
      SPM y(new MyValue(44));
      x = y;
      cout << "after assign" << endl;
    }
    cout << "out_of_y" << endl;
  }
  cout << "out_of_x" << endl;
}
-----
出力
cstr with value43
cstr with value44
obj 43 refcount 0
dstr43
obj 44 refcount 2
after assign
obj 44 refcount 1
out_of_y
obj 44 refcount 0
dstr44
out_of_x