在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存。这种内存管理的方式只需要程序员将new操作返回的指针作为auto_ptr的初始值即可,程序员不能显式的调用delete。如 auto_ptr(new int)。

  这在一定程度上避免了堆内存忘记释放造成的问题。不过auto_ptr也有一些缺点(拷贝是返回一个左值,不能调用delete[]等),所以在c++11中被废弃了。c++11标准照中改用unique_ptr,share_ptr,及weak_ptr等智能指针自动回收堆分配的对象。

  下面是一个用c++11中智能指针实现的一个例子:

#include <memory>
#include <iostream> using namespace std; int main()
{
unique_ptr<int> up1(new int()); //无法复制的unique_ptr
unique_ptr<int> up2 = up1; //不能通过编译 cout << *up1 << endl; // unique_ptr up3 = move(up1); //现在up3是数据唯一的unique_ptr只能指针 cout << *up3 << endl; //
cout << *up1 << endl; //运行时错误
up3.reset(); //显示释放内存
up1.reset(); //不会导致运行时错误 cout << *up3 << endl; //运行时错误 share_ptr<int> sp1(new int());
share_ptr<int> sp2 = sp1; //OK cout << *sp1 << endl; //
cout << *sp2 << endl; // sp1.reset();
cout << *sp2 << endl; //
}

  例子使用两种不同的智能指针unique_ptr和share_ptr来自动释放堆对象的内存。在析构或者调用reset都能释放对象。

  unique_ptr与所指的对象内存绑定紧密,不能与其他的unique_ptr类型的指针共享所指对象的内存。每个unique_ptr都唯一的拥有所指对象的内存。但是这种所有权可以通过标准库的move函数来转移,如unique_ptr up3 = move(up1),一旦转移成功,原先的 unique_ptr就失去了对象内存的所有权,再使用已经失去权力的unique_ptr就会出现运行错误。

  从实现上讲,unique_ptr是删除了拷贝构造函数,保留了移动构造函数的封装类型,程序仅可以使用右值对unique_ptr进行构造,一旦构造成功,右值对象中的指针失效。

  share_ptr则不同,它允许多个该智能指针共享的永远同一堆分配对象的内存。与unique_ptr不同的是在实现上采用了引用计数,所以,一旦某个share_ptr失去了所有权,其他指针并没有影响,例子中sp1和sp2都共享指针,在sp1 reset之后只会使计数器降低,而不会导致内存的释放,当sp2 reset之后,导致引用计数器为零,share_ptr才会真正释放占有的内存空间。

  在c++11标准中,除了share_ptr和unique_ptr之外 ,还有weak_ptr。

  weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个shared_ptr管理的对象,却并不拥有该对象。将一个weak_ptr绑定到shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。

  当我们创建一个weak_ptr时,要用一个shared_ptr来初始化它:

auto p=make_shared_ptr<int>();

weak_ptr<int> wp(p); //wp弱共享p,p的引用计数未改变

  由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock()。此函数检查weak_ptr指向的对象是否存在。使用weak_ptr的成员lock,则可返回内存中的一个share_ptr对象,并在所指向的对象无效时候,返回空。

#include <memeroy>
#include <iostream> using namespace std; void Check(weal_ptr<int> & wp)
{
share_ptr<int> sp = wp.lock(); //转换为share_ptr<int>
if(sp != nullptr)
{
cout << "still" << *sp << endl;
}
else
{
cout << "pointer is invalid." << endl;
}
} int main()
{
share_ptr<int> sp1(new int());
share_ptr<int> sp2 = sp1;
weal_ptr<int> wp = sp1;//指向share_ptr<int> 所指对象 cout << *sp1 << endl; //
cout << *sp2 << endl; //
Check(wp); //still 22 sp1.reset();
cout << *sp2 << endl; //
Check(wp);     //still 22 sp2.reset();
Check(wp);     //pointer is invalid. return ;
}

  例子中,sp1和sp2为共享对象,而weak_ptr指针wp也指向该内存,在sp1和sp2都有效的时候,调用weak_ptr的lock函数返回一个可用的share_ptr使用;当sp1和sp2都调用reset之后,会使堆内存的引用计数器降低为0,而一旦计数器降低为0,share_ptr就会释放内存,使之失效,此时调用weak_ptr的lock时,返回空指针nullptr。

c++11之智能指针的更多相关文章

  1. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  2. C++11 shared_ptr智能指针(超级详细)

    在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如: 有些内存资源已经被释放,但指向它的指针并没 ...

  3. C++11 unique_ptr智能指针详解

    在<C++11 shared_ptr智能指针>的基础上,本节继续讲解 C++11 标准提供的另一种智能指针,即 unique_ptr 智能指针. 作为智能指针的一种,unique_ptr ...

  4. C++11中智能指针的原理、使用、实现

    目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序 ...

  5. C++11 weak_ptr智能指针

    和 shared_ptr.unique_ptr 类型指针一样,weak_ptr 智能指针也是以模板类的方式实现的.weak_ptr<T>( T 为指针所指数据的类型)定义在<memo ...

  6. C++11智能指针

    今晚跟同学谈了一下智能指针,突然想要看一下C++11的智能指针的实现,因此下了这篇博文. 以下代码出自于VS2012 <memory> template<class _Ty> ...

  7. C++11智能指针的深度理解

    平时习惯使用cocos2d-x的Ref内存模式,回过头来在控制台项目中觉得c++的智能指针有点生疏,于是便重温一下.首先有请c++智能指针们登场: std::auto_ptr.std::unique_ ...

  8. Qt智能指针简明说明

    下面的智能指针分别对应boost库,Qt库,c++11的智能指针 boost::scoped_ptr  QScopedPointer unique_ptr 在其生命期结束后会自动删除它所指的对象(确定 ...

  9. [翻译]将智能指针用于C++的类成员

    http://stackoverflow.com/questions/15648844/using-smart-pointers-for-class-members Question: I'm hav ...

随机推荐

  1. Mac 版 QQ 可直接访问 iPhone 的相册 ?!

    在QQ的聊天窗口中,点击 发送图片 的按钮,会有两个选择项,其中一个就是 从iPhone相册中选取 ,如图 点击  从iPhone相册中选取 后,iPhone上的QQ会收到一条消息 “请选择要上传的照 ...

  2. vc 6.0 连接数据库

    在mysql的文档(C:\Program Files\MySQL\MySQL Server 5.5\lib)里面找到libmysql.dll和libmysql.lib 两个文件,将他们移到 工程文件下 ...

  3. Vim 新用法

    daw , delete a word cw , delete from cursor to the end then insert mode a word 移动: f ; Aa Oo Cc Ii S ...

  4. Java中的public、protected、default和private的区别

    (1)       对于public修饰符,它具有最大的访问权限,可以访问任何一个在CLASSPATH下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. (2)      ...

  5. [CFGym101061G] Repeat it(逆元)

    题目链接:http://codeforces.com/gym/101061/problem/G 题意:给一个数字n,让你重复m次,求最后这个数对1e9+7取模的结果. 思路:设数字n长度为k,重复m次 ...

  6. [NYIST32]组合数(状压,枚举,暴力)

    题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=32 求n个数中挑出r个数字的所有情况,最后倒序输出所有情况. 状压枚举所有情况就是了 ...

  7. 计算机术语install和setup的区别

    作为安装程序的Setup文件是软件的开发者专门为其软件设计的.exe文件,是当前最为盛行的安装程序.在运行该Setup文件进行软件安装时,Setup除了进行复制.改名.解压和目录维护等基本安装工作外, ...

  8. Hibernate 的<generator class="native"></generator>的不同属性含义

    1) assigned主键由外部程序负责生成,无需Hibernate参与. 2) hilo通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态. 3) seqhilo与hil ...

  9. android 事件处理机制之requestDisallowInterceptTouchEvent

    当手指触摸到屏幕时,系统就会调用相应View的onTouchEvent,并传入一系列的action.当有多个层级的View时,在父层级允许的情 况下,这个action会一直向下传递直到遇到最深层的Vi ...

  10. jstl的forEach使用和jstl变量实现自增

    <c:forEach items="${reallyChooseSubjectList}" var="reallyChooseSubject"> & ...