1.画出下面程序的内存分布图
template<class _Ty>
class RefCnt
{
public:
_Ty* _Ptr;
std::atomic_int _Uses;
std::atomic_int _Weaks;
public:
RefCnt(_Ty* p) :_Ptr(p), _Uses(1), _Weaks(1)) {}
~RefCnt() {}
void _Incref() { _Uses += 1; }
void _Incwref() { _Weaks += 1; }
};
template<class _Ty> class my_weak_ptr;
template<class _Ty,class _Dx = MyDeletor<_Ty>>
class my_shared_ptr
{
private:
_Ty* _Ptr;
RefCnt<_Ty>* _Rep;
_Dx _mDeletor;
public:
my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
{
if (p != NULL)
{
_Ptr = p;
_Rep = new RefCnt<_Ty>(p);
}
}
~my_shared_ptr()
{
if (_Rep != nullptr && --_Rep->_Uses == 0)
{
_mDeletor(_Ptr);
if (--_Rep->_Weaks == 0)
{
delete _Rep;
}
}
_Ptr = NULL;
_Rep = NULL;
}
};
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x) { cout << "Object" << endl; }
~Object() {cout << "~Object" <<endl; }
void Print() const { cout << "value:" << value << endl; }
};
int main()
{
my_shared_ptr<Object> op1(new Object(10));
return 0;
}
2._Uses的意思是如果_Uses为0,表示要删掉对象Object,_Uses主要标识引用对象的个数,_Weaks为0表示要把RefCnt这个结构删掉,_Weaks主要标识弱引用对象的个数
3.画出上面程序的内存分布图
template<class _Ty>
class RefCnt
{
public:
_Ty* _Ptr;
std::atomic_int _Uses;
std::atomic_int _Weaks;
public:
RefCnt(_Ty* p) :_Ptr(p), _Uses(1), _Weaks(1)) {}
~RefCnt() {}
void _Incref() { _Uses += 1; }
void _Incwref() { _Weaks += 1; }
};
template<class _Ty> class my_weak_ptr;
template<class _Ty,class _Dx = MyDeletor<_Ty>>
class my_shared_ptr
{
private:
_Ty* _Ptr;
RefCnt<_Ty>* _Rep;
_Dx _mDeletor;
public:
my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
{
if (p != NULL)
{
_Ptr = p;
_Rep = new RefCnt<_Ty>(p);
}
}
~my_shared_ptr()
{
if (_Rep != nullptr && --_Rep->_Uses == 0)
{
_mDeletor(_Ptr);
if (--_Rep->_Weaks == 0)
{
delete _Rep;
}
}
_Ptr = NULL;
_Rep = NULL;
}
};
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x) { cout << "Object" << endl; }
~Object() {cout << "~Object" <<endl; }
void Print() const { cout << "value:" << value << endl; }
};
template<class _Ty>
class my_weak_ptr
{
private:
RefCnt<_Ty>* _Rep;
};
int main()
{
my_shared_ptr<Object> op1(new Object(10));
my_weak_ptr<Object> wp(op1);
return 0;
}
4.弱引用不需要删除器
5.存在弱指针对弱指针赋值,存在弱指针对强指针赋值,不存在强指针对弱指针赋值,强指针是拥有资源,如果强指针对弱指针赋值,是把强指针的资源交给弱指针,但是弱指针不能拥有资源,弱指针只是一种检测,检测结构是否存在,主要解决环形引用
6.真正的资源拥有者是共享指针对象(shared_ptr),而弱引用对象并不控制资源(weak_ptr),弱引用对象控制的是引用计数这个结构,这个结构存在并不一定对象(Object)就存在,当引用计数结构中_Uses大于等于1时,Object对象才存在,如果_Uses为0说明对象不存在,如果_Weaks大于等与1,说明这个引用计数结构还存在,如果_Weaks等于0,说明这个引用计数结构不存在了
7.画出下面程序的结构图
class Child;
class Parent
{
public:
my_weak_ptr<Child> c;
public:
Parent() { cout << "Parent" << endl; }
~Parent() { cout << "~Parent" << endl; }
void hi() const { cout << "hello parent" << endl; }
};
class Child
{
public:
my_weak_ptr<Parent> p;
Child() { cout << "Child" << endl; }
~Child() { cout << "~Child" << endl; }
};
void fun()
{
my_shared_ptr<Parent> parent(new Parent());
my_shared_ptr<Child> child(new Child());
parent->c = child;
child->p = parent;
child->p.lock()->hi();
}
int main()
{
fun();
return 0;
}
循环引用,parent指针和child指针的计数结构的弱指针引用都为2,当销毁的时候,先销毁child指针,调动child指针的析构函数,先判断child指针的强引用(_Uses)减一是否为0,结果为0则要调动删除器销毁child对象,child对象中有一个弱引用指针c,销毁child对象的时候要先释放child对象拥有的资源,所以要先判断parent指针的弱引用(_Weaks)减一是否为0,结果为1,不为0,不删除parent的引用计数结构,返回到child对象的析构函数中,析构掉child对象,再返回到child指针的析构函数中,继续判断child指针的_Weaks减一是否为0,结果为1,所以child的引用计数结构不删除
当销毁parent指针的时候,先判断parent指针的_Uses减一是否为0,结果为0则要调动删除器销毁parent对象,parent对象中有一个弱引用指针p,销毁parent对象的时候要释放parent对象拥有的资源,所以要先判断child指针的_Weaks减一是否为0,结果为0,要先释放child指针的引用计数结构,释放完以后,回到parent对象的析构函数中,析构掉parent对象,再回到parent的析构函数中,继续判断parent的_Weaks减一是否为0,结果为0,要释放parent的引用计数结构
也就是说parent销毁了三个结构(parent对象和parent的引用计数结构和child的引用计数结构),child销毁了一个结构(child对象)
8.如何克服循环引用? 答案:使用弱引用(weak_ptr)
9.销毁的顺序是什么呢? 答案:①child对象②child的引用计数结构③parent对象④parent的引用计数结构
|