简介
C++11 智能指针
文章目录
前言
一、什么是智能指针?
shared_ptr 强智能指针,可以改变资源的引用计数
weak_ptr 弱智能指针,不会改变资源的引用计数
unique_ptr 独占式智能指针,只能转移,不能赋值
二、智能指针的原理
shared_ptr采用了引用计数器,允许多个指针指向同一个对象。每一个shared_ptr的拷贝都指向相同的内存,并共同维护同一个引用计数器,记录同一个实例被引用的次数。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
三、什么是智能指针循环引用?
1.未循环引用情况
1.1 代码如下
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class BTest;
class ATest
{
public:
ATest(){
cout << "ATest 构造成功!" << endl;
}
~ATest(){
cout << "ATest 析构成功!" << endl;
}
public:
shared_ptr<B> m_bptr; //引用
};
class BTest
{
public:
BTest(){
cout << "BTest 构造成功!" << endl;
}
~BTest(){
cout << "BTest 析构成功!" << endl;
}
public:
shared_ptr<A> m_aptr; //引用
};
//使用
void test01()
{
shared_ptr<ATest> pa(new ATest());
shared_ptr<BTest> pb(new BTest());
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
1.2 结果如下
表明,ATest和BTest两个类的析构函数正常调用,表明内存正确释放。
2.循环引用情况
2.1 代码如下
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class BTest;
class ATest
{
public:
ATest(){
cout << "ATest 构造成功!" << endl;
}
~ATest(){
cout << "ATest 析构成功!" << endl;
}
public:
shared_ptr<B> m_bptr; //引用
};
class BTest
{
public:
BTest(){
cout << "BTest 构造成功!" << endl;
}
~BTest(){
cout << "BTest 析构成功!" << endl;
}
public:
shared_ptr<A> m_aptr; //引用
};
//使用
void test02()
{
shared_ptr<ATest> pa(new ATest()); //使用
shared_ptr<BTest> pb(new BTest()); //使用
pa->m_bptr = pb;
pb->m_aptr = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
2.2 结果如下
表明,ATest和BTest两个类的析构函数未调用,表明内存未正确释放。
四、智能指针循环引用会导致什么问题?
如上2.2结果所示,智能指针的循环引用会造成new出来的资源无法释放,导致内存泄露问题。
五、怎么解决智能指针循环引用问题?
1.方法
定义对象的时候,用强智能指针;引用对象的地方,用弱智能指针
2. 代码如下
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class BTest;
class ATest
{
public:
ATest(){
cout << "ATest 构造成功!" << endl;
}
~ATest(){
cout << "ATest 析构成功!" << endl;
}
public:
//将shared_ptr改为了weak_ptr
weak_ptr<B> m_bptr; //引用
};
class BTest
{
public:
BTest(){
cout << "BTest 构造成功!" << endl;
}
~BTest(){
cout << "BTest 析构成功!" << endl;
}
public:
//将shared_ptr改为了weak_ptr
weak_ptr<A> m_aptr; //引用
};
//使用
void test03()
{
shared_ptr<ATest> pa(new ATest()); //使用
shared_ptr<BTest> pb(new BTest()); //使用
pa->m_bptr = pb;
pb->m_aptr = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
3. 结果
结果,与《未循环引用情况》一致,表明,资源正确释放。
六、成员方法调用问题
1. 场景
2. 代码如下
#include<iostream>
#include<string>
#include<memory>
using namespace std;
/*
*/
class BTest;
class ATest
{
public:
ATest(){
cout << "ATest 构造成功!" << endl;
}
~ATest(){
cout << "ATest 析构成功!" << endl;
}
void funA()
{
cout << "ATest对象的fun方法!" << endl;
}
public:
weak_ptr<BTest> m_bptr; //引用
};
class BTest
{
public:
BTest(){
cout << "BTest 构造成功!" << endl;
}
~BTest(){
cout << "BTest 析构成功!" << endl;
}
void funB()
{
shared_ptr<ATest> usptr = m_aptr.lock(); //提升方法
if (usptr!=nullptr)
{
usptr->funA();
}
//m_aptr->funA(); // 弱智能指针不能调用
}
public:
weak_ptr<ATest> m_aptr; //引用
};
void test04()
{
shared_ptr<ATest> pa(new ATest()); //使用
shared_ptr<BTest> pb(new BTest()); //使用
pa->m_bptr = pb;
pb->m_aptr = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
pb->funB();
}
int main()
{
test04();
system("pause");
return 0;
}
3. 结果
成功调用。
总结
weak_ptr与shared_ptr配合使用。
待完善。。。。。
《C++智能指针——shared_ptr的使用》