关于智能指针的研究
Posted songyuchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于智能指针的研究相关的知识,希望对你有一定的参考价值。
最近面试的时候面试官问了我一个问题。unique_ptr和shared_ptr到底有什么区别?我一时语塞。回来之后我痛定思痛,决定好好的研究一下智能指针的问题。现在已经研究的差不多了,决定好好的总结一下。
一、智能指针的用途
二、智能指针的特性
三、智能指针的种类与用途
3.1 最原始的智能指针auto_ptr
3.2 独一无二的智能指针unique_ptr
3.3 可以共享的指针shared_ptr
3.4 智能指针的用途
3.4.1 智能指针的用途
3.4.2 unique_ptr和shared_ptr的用途
四、总结
一、智能指针的用途
首先我们先设置一种场景,假如我们当前有一个类,类中存放着一个指针用来保存字符串,那么我们应该怎么写呢?
class CopyConstructor
{
public:
char *p;
public:
CopyConstructor(char *str);
virtual ~CopyConstructor();
CopyConstructor(CopyConstructor &m_copCon);
CopyConstructor operator = (const CopyConstructor &m_copCon);
void print();
};
好的,那么我们再构造函数中如果想要初始化字符串可以这样写。
CopyConstructor::CopyConstructor(char *str)
{
cout<<"CopyConstructor::CopyConstructor"<<endl;
p = new char[strlen(str) + 1];
strncpy(p, str, strlen(str) + 1);
}
如果我们现在提出一个需求,就是要让两个对象之间可赋值,就像这样:
CopyConstructor copConFirst(str);
CopyConstructor copConSecond(str2);
copConSecond = copConFirst;
但是如果这样写的话就会面临一个问题,就是析构函数怎么写?换句话说再析构函数中是否使用delete函数回收之前new出来的空间。那么我们分析一下这个问题
假如我们不写delete函数,那么当然程序就会导致内存泄漏了,这个恐怕是不成的。
假如我们写delete函数,那么会导致一个什么结果呢?它只拷贝了指针,但是实际delete掉的是同一个内存空间,会直接导致段错误的。
好的,为了解决这个问题,我们有三种方法可以解决:
(1)写一个运算符重载函数,重载=,关于这个的写法请大家参考我的博客《关于拷贝构造函数和运算符重载的问题》。
(2)使用智能指针。
二、智能指针的特性
那么为什么智能指针能解决上述问题呢?因为他有两个特性。第一个特性就是自动进行delete,换句话说就算你不写delete那么它也能再最后回收那块空间,绝对不会说内存泄漏这种情况发生。第二个特性就是智能指针是一个指针跟一个空间相对应。(我们先不讨论shared_ptr)。这样就不会导致delete两次了。
三、智能指针的种类和用途
3.1 最原始的智能指针auto_ptr
auto_ptr是最原始的智能指针。他有以下几个特性:1、只要是c++的版本,都能使用auto_ptr,不像后面两种必须使用c++11的版本才行。2、auto_ptr再相互赋值时,会先把原来的指针移成空,然后再把新来的指针指向原来的指针指向的空间。3、auto_ptr只能支持delete,不支持delete []。当然了,它的特性来说的话还是都支持的。
3.2 独一无二的智能指针unique_ptr
正因为有上述第二,第三两个问题,因此c++11才出了unique_ptr,它的特性如下:1、unique_ptr是只有c++11版本才能使用的。因此再编译或者再编写makefile的时候要注意以下。2、unique_ptr再相互赋值的时候不能使用=(即copConSecond = copConFirst这样写不可以的)。必须要有恰当的函数。3、unique_ptr可以支持delete []。
这里稍微说以下如何用unique_ptr进行相互赋值,这当中有三种情况,第一种情况是两个指针都是unique_ptr,第二个情况是我要把unique_ptr变成普通指针,第三种情况是我要把普通指针变成unique_ptr。我们举个例子
unique_ptr <AutoPtr> autoPtrFirst(new AutoPtr(1));
unique_ptr <AutoPtr> autoPtrSecond(new AutoPtr(2));
AutoPtr *p = NULL;
好,我们针对以上三种情况进行讨论。
第一种情况:假如我们要把autoPtrSecond指向autoPtrFirst那么我们应该怎么做呢?我们可以这样写。autoPtrSecond = std::move(autoPtrFirst),即把First指针移动走,只留下Second指针。
第二种情况:如果我要把unique_ptr指针变成普通指针应该怎么做呢?我们可以这样写。p = autoPtrFirst.release(),这样我们就可以把autoPtrFirst移动走,然后让p指向原来的地址空间了。
第二种情况:如果我要把unique_ptr指针变成普通指针应该怎么做呢?我们可以这样写。p = autoPtrFirst.release(),这样我们就可以把autoPtrFirst移动走,然后让p指向原来的地址空间了。
第三种情况:如果我们要把普通指针变成unique_ptr指针应该怎么做呢?我们可以这样写。autoPtrFirst.reset(p),这样我们就可以将autoPtrFirst指向p了。
3.3 可以进行共享的指针
好的,那么我们看完了前两种智能指针我们可能会产生一个问题:为啥不能两个智能指针指向同一块内存空间呢?答案是可以的。我们使用shared_ptr就可以了。
关于shared_ptr里面的实现方法我们再这里不做过多的研究和探讨。我们只研究shared_ptr里面的特性。它的特性有如下几点:1、shared_ptr是只有c++11版本才能使用的。因此再编译或者再编写makefile的时候要注意一下。2、shared_ptr和前两者最大的不同在于它支持两个指针指向同一块内存。3、shared_ptr支持delete []。
3.4 智能指针的用法
3.4.1 智能指针的用途
智能指针对于动态分配内存来说非常的方便,但是有以下几个缺点:
1、智能指针相当于是传指针,这样比传对象要麻烦不少。
2、智能指针不太容易知道什么时候结束这个对象,因此对我们分析代码不是一个好的选择。
3.4.2 关于unique_ptr和shared_ptr的用途
首先说明一下,auto_ptr这个基本上到c++11以后就被弃用了,基本用的还是后两种。前者一般来说有比较好的安全管理机制,后者来说比较方便。所以各有优劣。
四、总结
本文主要研究了智能指针的用途,种类,区别等等。
以上是关于关于智能指针的研究的主要内容,如果未能解决你的问题,请参考以下文章