#include <bits/stdc++.h>
#include <memory>//智能指针头文件
using namespace std;
int main(){
/*
1.auto_ptr 已经被C++11废弃了,所有权模式,
当两个auto_ptr 指针指向同一个地址时,
当一个指针释放内存时,
另外一个指针还是指向这个地址,
并且可以这个指针访问,但是会导致程序崩溃
auto_ptr建议改用uniqu_ptr
*/
auto_ptr<int> p1(new int(10));
cout<<"p1指向的地址的内容 "<<*p1<<endl;
auto_ptr<int> p2 = p1;//编译器支持这种写法,p2剥夺p1的所有权,但是p1依然可以访问,会导致崩溃
//cout<<*p1<<endl;
/*
2.unique_ptr 不支持赋值操作,更安全
可以使用move函数进行所有权变更
*/
unique_ptr<int> p3(new int(11));
cout<<"p3指向的地址的内容 "<<*p3<<endl;
//unique_ptr<int> p4 = p3; //编译器不支持这种写法,但可以使用move
unique_ptr<int> p4 = move(p3);
cout<<"p3指向的地址 "<<p3.get()<<endl; //置为NULL了
cout<<"p4指向的地址的内容 "<<*p4<<endl;
/*
3.shared_ptr 共享机制,
对于指向的那个地址有一个引用计数(use_count方法可以查看),
当引用计数为0时才释放指向的内存
但存在一个bug:
当两个对象同时使用一个shared_ptr成员变量指向对方,
会造成循环引用,使引用计数失效,从而导致内存泄露
*/
shared_ptr<int> p5(new int(12));
shared_ptr<int> p6 = p5;cout<<"p6指向的地址的内容 "<<*p6<<endl;
shared_ptr<int> p7 = p6;cout<<"p7指向的地址的内容 "<<*p7<<endl;
cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
cout<<"p5指向的地址 "<<p5.get()<<endl;//p5指向的地址
cout<<"p6指向的地址 "<<p6.get()<<endl;//p6指向的地址
cout<<"p7指向的地址 "<<p7.get()<<endl;//p7指向的地址,同一个地址
p7.reset();//引用数减1
cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
cout<<"p5指向的地址的内容 "<<*p5<<endl;
p6.reset();//引用数减1
p5.reset();//引用数减1
cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
cout<<"p5指向的地址 "<<p5.get()<<endl;//引用数为0,指向的空间释放了,指向了NULL
/*
4.weak_ptr
进行该对象的内存管理的是那个强引用的 shared_ptr。
weak_ptr只是提供了对管理对象的一个访问手段。
只能由一个shared_ptr或另外一个weak_ptr对weak_ptr进行初始化
它的构造和析构不会引起引用记数的增加或减少。
不能通过weak_ptr直接访问对象的方法,需要先转换为转化为shared_ptr
通过调用lock函数来获得shared_ptr
weak_ptr本身也是一个模板类,
但是不能直接用它来定义一个智能指针的对象,
只能配合shared_ptr来使用,
可以将shared_ptr的对象赋值给weak_ptr,
并且这样并不会改变引用计数的值。
查看weak_ptr的代码时发现,
它主要有lock、swap、reset、expired、operator=、use_count几个函数,
与shared_ptr相比多了lock、expired函数,
但是却少了get函数,甚至连operator* 和 operator->都没有
*/
shared_ptr<int> p8(new int(13));
cout<<"p8指向的地址引用数 "<<p8.use_count()<<endl;//引用数
weak_ptr<int> p9(p8); //不改变引用数目
cout<<"p8指向的地址引用数 "<<p8.use_count()<<endl;//引用数
//cout<<*p9<<endl;//没有对weak_ptr进行*的重载,无法取到指向的地址的值,需要先转换成shared_ptr
cout<<"p9指向的地址的内容 "<<*(p9.lock())<<endl; //使用lock()方法获取shared_ptr
return 0;
}
运行结果:
weak_ptr在类中的使用,解决shared_ptr循环引用问题
#include <bits/stdc++.h>
#include <memory>//智能指针头文件
using namespace std;
class TestShared{
public:
char name;
shared_ptr<TestShared> p;
TestShared(char value){
name = value;
cout<<"TestShared 构造函数被调用"<<endl;
}
~TestShared(){
cout<<"TestShared对象"<<name<<"的析构函数被调用"<<endl;
p.reset();
}
};
class TestWeak{
public:
char name;
weak_ptr<TestWeak> p;
TestWeak(char value){
name = value;
cout<<"TestWeak 构造函数被调用"<<endl;
}
~TestWeak(){
cout<<"TestWeak对象"<<name<<"的析构函数被调用"<<endl;
p.reset();
}
};
void testSharePtr(){
shared_ptr<TestShared> p1(new TestShared('a')), p2(new TestShared('b'));
//循环引用,造成内存泄露
cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
p1->p = p2;
p2->p = p1;
cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
cout<<"程序结束"<<endl;
return ;
}
void testWeakPtr(){
shared_ptr<TestWeak> p1(new TestWeak('a')), p2(new TestWeak('b'));
//正常析构
cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
p1->p = p2;
p2->p = p1;
cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
cout<<"程序结束"<<endl;
return ;
}
int main(){
testSharePtr();
cout<<"--------------------------"<<endl;
testWeakPtr();
return 0;
}
运行结果: