}
}
void addRef() {
mcount++;
}
int delRef() {
return --mcount;
}
private:
TT* mptr;
int mcount;
};
template
class smart_ptr {
public:
smart_ptr(T* ptr = nullptr){
mptr = ptr;
mRefCnt = new Refcnt(mptr);
}
~smart_ptr() {
if (0 == mRefCnt->delRef()) {
delete mptr;
mptr = nullptr;
}
}
T& operator*() {
return *(this->mptr);
}
T* operator->() {
return this->mptr;
}
smart_ptr(const smart_ptr& ptr) {
mptr = ptr.mptr;
mRefCnt = ptr.mRefCnt;
if (mptr != nullptr) {
mRefCnt->addRef();
}
}
smart_ptr& operator=(smart_ptr &ptr) {
if (this == &ptr) {
return *this;
}
//要走之前,要先判断一下自己原先的资源有没有人接管
if (0 == mRefCnt->delRef()) {
delete mptr;
}
mptr = ptr.mptr;
mRefCnt = ptr->mRefCnt;
mRefCnt->addRef();
return *this;
}
private:
T* mptr; //指向资源
Refcnt* mRefCnt; //指向引用计数
};
int main() {
smart_ptr sp(new int); //现在这样写就好了
smart_ptr ps(sp);
return 0;
}
强智能指针
使用引用计数的指针有:shared_ptr 和 weak_ptr,一个称为强智能指针,一个称为若智能指针。
强智能指针可以改变资源的引用计数,弱智能指针不会。
我们前面写的那个就是简化版的强智能指针。
但是呢,强智能指针有个很严重的问题,叫做循环引用,或者说“交叉引用”,这么说会不会比较明显点。
#include
#include
using namespace std;
class B;
class A {
public:
A() {
cout << “A” << endl;
}
~A() {
cout << “~A” << endl;
}
shared_ptr _ptrb;
};
class B {
public:
B() {
cout << “B” << endl;
}
~B() {
cout << “~B” << endl;
}
shared_ptr _ptra;
};
int main() {
shared_ptr pa(new A());
shared_ptr pb(new B());
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
//到这之前都很正常
//pa->_ptrb = pb;
//pb->_ptra = pa;
return 0;
}
A
B
1
1
~B
~A
那我现在把那两行放出来运行呢?
int main() {
shared_ptr pa(new A());
shared_ptr pb(new B());
//到这之前都很正常
pa->_ptrb = pb;
pb->_ptra = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
return 0;
}
A
B
2
2
智能指针没有被正确的析构掉,那还能叫智能指针吗?
弱智能指针
从上面的实验我们得出一个结论:在使用对象的时候,使用强智能指针;在引用对象的时候,使用弱智能指针。
怎么得出的呢?总不能说强智能指针不好用了就用弱的吧,主要是弱智能指针不改变计数,但是其实就相当于是一个观察者,对对象其实没有权限的。
改一下上面的代码,把类中的强智能指针改成弱的。再运行就正常。
弱智能指针升级为强智能指针
接下来是不是就要问这个问题嘞?
类B里面去调用类A里面的一个方法,看看行不行。
void testB() {
_ptra->testA();
}
很显然,是不行的。因为弱智能指针只会观察强指针。
那要用的时候怎么办呢?升级:
void testB() {
shared_ptr ps = _ptra.lock(); //就是内个锁
if (ps != nullptr) { //看一下资源是否还在
ps->testA();
}
}