c++11之智能指针

由于在c++中我们可以动态分配内存,但有时候我们会忘记用

delete或free释放内存,就会导致内存泄露。所以c++11提供了智能指针这种东西

本文参考了知乎某知乎友的

https://www.zhihu.com/people/mo-shan-zhe/activities

比如下面这两种情况

//1 内存泄漏 str1所指的资源没有被释放
{
    string* str1 = new string("hello");
    string* str2 = new string("world");
}

//2 多重释放,引起程序崩溃
{
    string* str1 = new string("hello");
    delete str1;
    //...
    delete str1;//引起程序崩溃
}

 可能平时都写在一个文件不会忘记释放内存,但如果是一个大的项目就出问题了

然后是智能指针的赋值方式和普通指针有差异

可以在定义时就可以动态分配内存单元,但不允许先定义智能指针,再为其动态分配内存空间

 

再然后普通指针和智能指针之间的赋值也得很注意,

不能把智能指针指向普通内存变量,或者把非智能指针赋值给智能指针。

但可以把智能指针赋值给普通指针,但不是那么直接,需要通过智能指针的get()成员函数获取智能指针中的指针后

再赋值给普通指针

1.先说一下auto_prt是c++98标准定义的独占智能指针,这意味着

一个对象只能被一个auto_prt指向,两个同类型的auto_ptr不能指向同一个对象

指针的赋值或复制操作会改变对象所有权,被复制的auto_prt不再指向任何对象

#include<iostream>
#include<memory>
#include<string>
using namespace std;

int main()
{
	auto_ptr<string> p1(new string("hello world!"));
	auto_ptr<string> p2;
	p2 = p1;//p1不再指向任何对象,其所指对象被p2指向了
	//cout << *p1;//错误代码,因为p1不指向任何对象 

	cout << *p2 << endl; 
	//p1 = new string("hello")不能用这种方式给智能指针赋值
	auto_ptr<string> p3(p2); //p2不再指向任何对象,其所指对象被p3指向了
	cout << *p3 << endl;
	//cout << *p2 << endl;//错误代码,因为p1不指向任何对象 
	return 0;
}

  

运行是会有警告,

因为c++11不推荐使用auto_ptr,提出了unique_ptr来代替,用途和auto_ptr相同

c++11禁止unique_ptr之间的赋值,也不允许使用一个unique_ptr初始化其他指针,否则会出现编译错误

比如

int main()
{
	unique_ptr<string> p1(new string("hello world!"));
	unique_ptr<string> p2;
	p2 = p1;//错误 
	unique_ptr<string> p3(p1);//错误 
	//system("pause");
	return 0;
}

  

下面再来说shared_ptr

它是一种共享指针,也就是说多个指针可以同时指向一个对象。

c++11允许shared_ptr指针之间的赋值,也允许使用一个智能指针初始化其他指针

再看原理分析

1.当从堆上申请了一个资源时,我们就创建一个智能指针对象,使它指向这个资源,同时,

在堆上申请一个用于计数的资源,让后来所有的指向该资源的对象都共享这个计数资源,这样,引用计数的个数就只有一份。

2.当将ptr1对象赋值给对象ptr2时,其共享的引用计数变为2。

3.删除ptr2对象时,其对应的引用计数减为1。

4.删除ptr1对象时,引用计数变为0,则释放资源。

智能指针的一种实现方式

首先,智能指针是一个类,这样就可以使用构造函数和析构函数对引用计数进行维护;

其次,它要表现出指针的行为,并且使用起来也要像普通指针一样;

最后,智能指针对任何类型都可以使用,所以它应该是一个模板。

具体实现看知乎原文吧

我们看一个应用例子把,实现两个数交换

#include<iostream>
#include<memory>
using namespace std;

void swap(shared_ptr<int> a,shared_ptr<int> b)
{
	int t;
	t = *a;
	*a = *b;
	*b = t;
}

int main()
{
	shared_ptr<int> p1(new int(9));
	
	shared_ptr<int> p2 = p1;
	
	shared_ptr<int> p3(new(int)),p4(new int(8)),p5;
	
	cout << "p1 = " << *p1 << "	p4 = " << *p4 << endl;
	
	swap(p1,p4);
	
	cout << "p1 = " << *p1 << "	p4 = " << *p4 << endl;
	
	p3 = p4 = p5 = p1;
	
	cout << *p1 << "	" << *p2 << "	" << *p3 << "	" << *p4 << "	" << *p5 << endl;
	return 0;
}

  

上面的代码我们多次用了new动态分配内存空间,但我们并没有delete过,

由于shared_ptr的存在,它会自动回收,就不会造成内存泄露

同时c++11还提供了一个配合shared_ptr使用的弱智能指针weak_ptr,

用于解决两个shared_ptr指针应用之间的循环计数问题。这个我不敢看了后面再补吧

原文地址:https://www.cnblogs.com/mch5201314/p/11687609.html