shared_ptr
C++11中引入shared_ptr来简化内存的管理,当shared_ptr不再使用时,自动回收内存。
初始化
1)通过 make_shared赋值(推荐的初始化方式)
2)通过reset
3)通过赋值
int main(int argc, char* argv[])
{
cout << "**************implement an instance by make_shared **************************" << endl;
shared_ptr<CObject> pShare = make_shared<CObject>();
pShare.reset();
cout << "**************implement an instance new **************************" << endl;
CObject* pTemp = new CObject();
pShare.reset(pTemp);
shared_ptr<CObject> pShareB = pShare;
cout << "**************end **************************" << endl;
return 0;
}
运行结果
使用注意事项:
1)一旦shared_ptr被赋值,不建议直接使用原有指针来操作,一旦原来的指针被delete,shared_ptr再次进行析构时会crash。
int main(int argc, char* argv[])
{
cout << "**************implement an instance by make_shared **************************" << endl;
shared_ptr<CObject> pShare = make_shared<CObject>();
pShare.reset();
cout << "**************implement an instance new **************************" << endl;
CObject* pTemp = new CObject();
pShare.reset(pTemp);
shared_ptr<CObject> pShareB = pShare;
delete pTemp;
cout << "**************end **************************" << endl;
return 0;
}
2)避免循环引用
weak_ptr
为了解决循环引用,C++11也引入了weak_ptr
循环引用
#include <iostream>
#include <memory>
using namespace std;
class CSharedB;
class CSharedA
{
public:
CSharedA() { cout << "This is construct function of CSharedA." << endl; };
~CSharedA() { cout << "This is destruct function of CSharedA." << endl; };
void setShared(shared_ptr<CSharedB> pB) {m_pB = pB;}
private:
shared_ptr<CSharedB> m_pB;
};
class CSharedB
{
public:
CSharedB() { cout << "This is construct function of CSharedB." << endl; };
~CSharedB() { cout << "This is destruct function of CSharedB." << endl; };
void setShared(shared_ptr<CSharedA> pA) { m_pA = pA; }
private:
shared_ptr<CSharedA> m_pA;
};
int main(int argc, char* argv[])
{
cout << "**************implement an instance by make_shared **************************" << endl;
shared_ptr<CSharedA> pShareA = make_shared<CSharedA>();
shared_ptr<CSharedB> pShareB = make_shared<CSharedB>();
pShareA->setShared(pShareB);
pShareB->setShared(pShareA);
cout << "**************end **************************" << endl;
return 0;
}
可以看到两个对象都没有被析构,造成的内存泄露
如果此时将两个类的成员变量由shared_ptr改成weak_ptr
#include <iostream>
#include <memory>
using namespace std;
class CSharedB;
class CSharedA
{
public:
CSharedA() { cout << "This is construct function of CSharedA." << endl; };
~CSharedA() { cout << "This is destruct function of CSharedA." << endl; };
void setShared(shared_ptr<CSharedB> pB) {m_pB = pB;}
private:
weak_ptr<CSharedB> m_pB;
};
class CSharedB
{
public:
CSharedB() { cout << "This is construct function of CSharedB." << endl; };
~CSharedB() { cout << "This is destruct function of CSharedB." << endl; };
void setShared(shared_ptr<CSharedA> pA) { m_pA = pA; }
private:
weak_ptr<CSharedA> m_pA;
};
int main(int argc, char* argv[])
{
cout << "**************implement an instance by make_shared **************************" << endl;
shared_ptr<CSharedA> pShareA = make_shared<CSharedA>();
shared_ptr<CSharedB> pShareB = make_shared<CSharedB>();
pShareA->setShared(pShareB);
pShareB->setShared(pShareA);
cout << "**************end **************************" << endl;
return 0;
}
此时,析构函数被调用。
实现差异
shared_ptr和weak_ptr实现时有_Uses和_Weaks两个计数器, 当shared_ptr被初始化时, _Uses和_Weaks都会被赋值为1。
当weak_ptr被赋值后,_Weaks会被加1
当shared_ptr被赋值后,_Uses会加1
因为 shared_ptr在初始化后 _Uses和_Weaks都会被赋值为1,也就说weak_ptr的持有者永远不会析构对象,所以采用weak_ptr时,循环引用时,不会导致析构失败。