简单实现了一个线程不安全的版本:
#include <iostream>
using namespace std;
int new_cnt = 0;
int del_cnt = 0;
template <class T>
class Sptr
{
public:
// 默认构造和析构函数
Sptr(T *ptr = nullptr) // 此时编译器不会生成默认的构造函数 无论有没有默认的实参
: data_(ptr)
{
if (data_ != nullptr)
{
cout << "ref_cnt_ new cnt: " << ++new_cnt << endl;
ref_cnt_ = new int(1);
}
cout << "in default Sptr()" << endl;
}
~Sptr()
{
cout << "in ~Sptr()" << endl;
decreRefCnt();
}
// 拷贝构造和拷贝赋值运算符
Sptr(const Sptr &s)
{
data_ = s.data_;
ref_cnt_ = s.ref_cnt_;
increRefCnt();
cout << "in copy Sptr()" << endl;
}
Sptr &operator=(const Sptr &s) // 双目运算的重载,入参
{
cout << "in copy = Sptr()" << endl;
if (&s == this)
{
// 自拷贝 直接返回
return *this;
}
decreRefCnt(); // 自身原来指向的内存引用要减1
data_ = s.data_;
ref_cnt_ = s.ref_cnt_;
increRefCnt();
return *this;
}
// 移动构造和移动赋值运算符
Sptr(Sptr &&s)
{
cout << "in move Sptr()" << endl;
if (&s == this)
{
return;
}
data_ = s.data_;
ref_cnt_ = s.ref_cnt_;
s.data_ = nullptr;
s.ref_cnt_ = nullptr;
}
Sptr &operator=(Sptr &&s)
{
cout << "in move = Sptr()" << endl;
if (&s == this)
{
return *this;
}
decreRefCnt(); // 自身原来指向的内存引用要减1
data_ = s.data_;
ref_cnt_ = s.ref_cnt_;
s.data_ = nullptr;
s.ref_cnt_ = nullptr;
return *this;
}
int refCnt() const
{
if (ref_cnt_ == nullptr)
{
return -1;
}
cout << "ref_cnt:" << *ref_cnt_ << endl;
return (*ref_cnt_);
}
T &operator*() const // 单目运算 不带入参
{
return *data_;
}
T *operator->() const // 单目运算 不带入参
{
return data_;
}
T *get() const
{
return data_;
}
private:
void increRefCnt()
{
if (ref_cnt_ == nullptr)
{
return;
}
(*ref_cnt_)++;
}
void decreRefCnt()
{
if (ref_cnt_ == nullptr)
{
return;
}
(*ref_cnt_)--;
if (*ref_cnt_ == 0)
{
cout << "ref_cnt_ del cnt: " << ++del_cnt << endl;
delete data_;
delete ref_cnt_;
}
else if (*ref_cnt_ < 0)
{
cout << "ref_cnt_ del cnt: " << ++del_cnt << endl;
delete ref_cnt_;
}
}
T *data_ = nullptr;
int *ref_cnt_ = nullptr;
};
class A
{
public:
A();
A(int a) { num = a; }
~A();
int num = 10;
};
A::A()
{
cout << "in A()" << endl;
}
A::~A()
{
cout << "in ~A()" << endl;
}
int main()
{
Sptr<A> ptr = new A; // 默认构造
ptr.refCnt();
cout << "num is " << ptr->num++ << endl;
cout << "num is " << (*ptr).num++ << endl;
cout << "num is " << ptr.get()->num << endl;
Sptr<A> ptr1(ptr); // 拷贝构造
ptr1.refCnt();
ptr.refCnt();
Sptr<A> ptr2;
ptr2.refCnt();
ptr2 = ptr1; // 拷贝赋值
ptr2.refCnt();
ptr1.refCnt();
ptr.refCnt();
{
Sptr<A> tmp;
tmp.refCnt();
}
{
Sptr<A> ptr3 = std::move(ptr2); // 移动构造
ptr3.refCnt();
ptr1.refCnt();
ptr.refCnt();
Sptr<A> ptr4;
ptr4 = std::move(ptr3); // 移动赋值
ptr4.refCnt();
ptr1.refCnt();
ptr.refCnt();
cout << "ptr3.refCnt: " << ptr3.refCnt() << endl;
}
{
Sptr<A> a1;
auto a2 = a1;
}
return 0;
}