【C++】:智能指针

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bqw18744018044/article/details/88611252

一、 智能指针的作用

C++11引入了智能指针的概念。。在使用普通指针,容易造成内存泄露或者多次释放,因此为了更好的管理内存引入智能指针。

二、 智能指针的使用

智能指针包含在头文件中,包括shared_ptr、unique_ptr、weak_ptr。
1. shared_ptr
1.1 介绍
shared_ptr是一种智能指针,作用如同指针,但会记录有多少shared_ptr共同指向一个对象,这便是所谓的引用计数。一旦指向一个对象的最后一个指针被销毁,那么引用计数清空为0,这个对象会被自动删除。
1.2 初始化

	//三种初始化智能指针的方式
	int* p = new int(30);
	shared_ptr<int> bptr(p);//通过一个指向堆的指针进行初始化(指向栈的指针将出错)
	shared_ptr<int> aptr = make_shared<int>(20);//通过make_shape函数初始化
	shared_ptr<int> cptr(aptr);//通过另外一个智能指针初始化
	cout << "aptr.use_count() = " << aptr.use_count() <<"  value = "<<*aptr<<std::endl;
	cout << "bptr.use_count() = " << bptr.use_count() <<"  value = "<<*bptr<<std::endl;
	cout << "cptr.use_count() = " << cptr.use_count() <<"  value = "<<*cptr<<std::endl;

1.3 赋值与获得原始指针

	//赋值
	int* p = new int(30);
	shared_ptr<int> ptr1 = make_shared<int>(20);
	shared_ptr<int> ptr2 = make_shared<int>(30);
	//ptr1 = p;//错误,不能使用普通指针给智能指针赋值
	ptr1 = ptr2;//智能指针赋值
	cout<< "ptr1.use_count() = "<<ptr1.use_count()<<" value = "<<*ptr1<<endl;
	p = ptr1.get();//获得原始指针
	cout<<"value = "<<*p<<endl;

1.4 注意事项
1.4.1 不要用原始指针初始化多个shared_ptr,否则会造成二次释放同一内存;
1.4.2 避免循环引用,会导致无法正确释放内存,导致内存泄露;

class B;
class A{
public:
	shared_ptr<B> ptr;
};

class B{
public:
	shared_ptr<A> ptr;
};

int main()
{
	while(true){
		shared_ptr<A> pa(new A());
		shared_ptr<B> pb(new B());
		pa->ptr = pb;
		pb->ptr = pa;
	}
}

上面的代码中智能指针pa和pb的引用计数为2,处理自身的引用外还有对方的成员中的指针。当是在while循环结束时,pa和pb的析构函数会被调用,引用计数变为1。此时这两个对象均无法释放自身的内存空间,造成内存泄露。
2. unique_ptr
一个unique_ptr指针指向的对象,其他指针无法指向,即unique_ptr”唯一”拥有其所指对象。其生命周期从创建开始到离开作用域。
unique_ptr可以使用reset方法重新指定、通过move方法转移所有权或通过relese方法释放所有权;

int main()
{
	{
	unique_ptr<int> uptr(new int(10));
	//unique_ptr<int> uptr2 = uptr;  //不能拷贝
	//unique_ptr<int> uptr2(uptr);  //不能赋值
	unique_ptr<int> uptr2 = move(uptr);  //转换所有权
	uptr2.relese();  //释放所有权
	}
	//超过作用域,内存释放
}

3. weak_ptr
weak_ptr是为了配合shared_ptr而引入的一种智能指针,但是它不具有普通指针的行为,其没有重载操作符*和->,它最大的作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。
weak_ptr可以从一个shared_ptr或者另外一个weak_ptr对象构造,获得资源的观测权,但没有使用权,因此它的构造函数不会引起指针引用计数的增加。
使用weak_ptr的成员函数use_count()可以观测资源的引用计数。
weak_ptr的另一个重要的成员函数是lock(),其可以从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。

 	shared_ptr<int> sh_ptr = make_shared<int>(10);
	cout<<sh_ptr.use_count()<<endl;//1
	
	weak_ptr<int> wp(sh_ptr);//引用计数不增加
	cout<<wp.use_count()<<endl;//1
	
	if(!wp.expired()){
		shared_ptr<int> sh_ptr2 = wp.lock();//获得了sh_ptr的一个可以的shared_ptr,引用计数增加
		*sh_ptr = 100;
		cout<<wp.use_count()<<endl//2;
	}

将1.4.2中两个类内部的shared_ptr换成weak_ptr就可以解决循环引用的问题。

猜你喜欢

转载自blog.csdn.net/bqw18744018044/article/details/88611252