菜鸟笔记
提升您的技术认知

智能指针初识

智能指针作用:

​ 普通指针new以后,有的人忘记删除就会引起内存泄漏,而且删除时也会有一些问题,例如一片内存地址被同时删除多次就会引起程序崩溃。所以这个时候引进了智能指针,可以在离开作用域后自动释放。这里介绍4种智能指针,智能指针包含在头文件#include

1.auto_ptr

​ 它采用所有权模式。允许一个auto_ptr类型变量赋给另一个auto_ptr,程序不会报错,但是有些问题,代码如下

	auto_ptr<int>p1(new int(1));
	auto_ptr<int>p2;
	p2 = p1; //auto_ptr不会报错,此时不能访问p1,只能访问p2
	cout << *p1;
	cout << *p2;

会引起内存崩溃问题,所以在c++11中取消了auto_ptr

2.unique_str

​ c++11及以后都用这个,因为程序不允许一个unique_ptr类型变量赋给另一个unique_ptr,可以防止内存崩溃。

	unique_ptr<int> p1(new int(1));
	unique_ptr<int> p2;
	p2 = p1;   //报错

但是如果给unique_ptr类型赋一个消亡值则无所谓

unique_ptr<string> p3;
p3 = unique_ptr<string>(new string ("test"));   //这种可以 

3.shared_ptr

​ 和auto_ptr是相对的,shared_ptr是所有权模式,而shared_ptr则是共享模式,多个对象可以访问同一片区域,它使用计数机制来表明资源被几个指针共享,通过成员函数use_count()来查看资源的所有者个数当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。

	shared_ptr<string>p1(new string("test"));
	shared_ptr<string>p2;
	p2 = p1;
	cout << *p2 << " " << *p1;   //不会报错

4.weak_ptr

​ weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放,weak_ptr不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它

class B;
class A
{
  
public:
	shared_ptr<B> pb_;
	~A()
	{
  
		cout << "A delete\n";
	}
};
class B
{
  
public:
	shared_ptr<A> pa_;
	~B()
	{
  
		cout << "B delete\n";
	}
};
void fun()
{
  
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());
	pb->pa_ = pa;
	pa->pb_ = pb;
	cout << pb.use_count() << endl;
	cout << pa.use_count() << endl;
}
int main()
{
  
	fun();    //两个shared_ptr相互引用所以资源引用计数为2,跳出函数只减1,资源引用计数不为0,就不会调用析构函数
	return 0;
}

为了解决shared_ptr死锁问题把其中一个shared_ptr换成weak_ptr就行了

class B;
class A
{
  
public:
	weak_ptr<B> pb_;
	~A()
	{
  
		cout << "A delete\n";
	}
};
class B
{
  
public:
	shared_ptr<A> pa_;
	~B()
	{
  
		cout << "B delete\n";
	}
};
void fun()
{
  
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());
	pb->pa_ = pa;
	pa->pb_ = pb;
	cout << pb.use_count() << endl;
	cout << pa.use_count() << endl;
}
int main()
{
  
	fun();    //两个shared_ptr相互引用所以资源引用计数为2,跳出函数只减1,资源引用计数不为0,就不会调用析构函数,用了weak_ptr以后资源引用计数不会增加也不会减少,只和shared_ptr有关
	return 0;
}