智能指针

  • 在C++库中最重要的类模板之一
  • 智能指针实际上是将指针封装在一个类里,通过对象管理指针.

STL中的智能指针auto_ptr

头文件: <memory>

  • 生命周期结束时,自动摧毁指向的内存空间
  • 不能指向堆数组(因为auto_ptr的析构函数删除指针用的是delete,而不是delete[])
  • auto_ptr的构造函数为explicit类型,所以只能显示初始化,比如:
  auto_ptr<int> ap1(new int());      //初始化正确,创建ap1类模板对象,使类模板里的指针为int*型,并指向1的地址

  int* p = new int();
  auto_ptr<int> ap2(p); //初始化正确   // auto_ptr<int> ap3 = new int(2); //出错,不能隐式初始化
  • 提供get()成员函数,可以用来查看类里的指针地址.比如:
  auto_ptr<int> ap(new int());
  cout<< ap.get()<<endl; //打印数值1的地址 : 0x6d2d18   int *p =ap.get();
  cout<< *p<<endl; //打印数值1
  • 一片堆空间只属于一个智能指针对象(因为多个指向相同地址的智能指针调用析构函数时,会出现bug)
  • 当auto_ptr被拷贝或赋值后,则自身的指针指向的地址会被抢占,比如:
  auto_ptr<int> p1(new int());
  auto_ptr<int> p2(new int());   p1 =p2; //首先会delete p1对象的类成员指针,然后将p2对象的类成员指针赋值给p1, 最后修改p2指针地址为NULL   cout<<"p2 ="<<p2.get()<<endl; //打印 : p2=0   //cout<<*p2<<endl; //出错,因为p2=0

初探auto_ptr智能指针

#include <iostream>
#include <memory> using namespace std; class Test
{
public:
int mvalue;
Test(int i=)
{
mvalue=i;
cout<< "Test("<<mvalue<<")"<<endl;
}
~Test()
{
cout<< "~Test("<<mvalue<<")"<<endl;
}
}; void func() //在func函数里使用auto_ptr
{
auto_ptr<Test> p1(new Test());
cout<<"p1 ="<<p1.get()<<endl; cout<<endl; auto_ptr<Test> p2(new Test());
cout<<"p2 ="<<p2.get()<<endl; cout<<endl; cout<<"p1=p2"<<endl;
p1=p2; cout<<endl; cout<<"p1 ="<<p1.get()<<endl;
cout<<"p2 ="<<p2.get()<<endl;
} int main()
{
cout<<"*****begin*****"<<endl;
func();
cout<<"*****end*****"<<endl; return ;
}

运行打印:

*****begin*****
Test()
p1 =0x8db1008 Test()
p2 =0x8db1018 p1=p2
~Test() p1 =0x8db1018
p2 =
~Test()
*****end*****

从结果可以看到,由于func()的生命周期结束,所以里面的auto_ptr指针自动就被释放了。

可以发现在调用p1=p2时, 首先会delete p1对象的类成员指针(调用~Test(1)析构函数),然后将p2对象的类成员指针赋值给p1(p1=0x8db1018), 最后修改p2指针地址为NULL(p2 =0)

 

STL中的智能指针shared_ptr(需要C++11支持)

  • 带有引用计数机制,支持多个指针对象指向同一片内存(实现共享)
  • 提供swap()成员函数,用来交换两个相同类型的对象,比如:
  shared_ptr<int> p1(new int());
  shared_ptr<int> p2(new int());   p1.swap(p2); //交换后 p1=2,p2=1   cout<< *p1 <<endl; //打印 2
  cout<< *p2 <<endl; //打印 1
  • 提供unique()成员函数, 判断该指针对象地址是否被其它指针对象引用
  • 提供get()成员函数,用来获取指针对象指向的地址
  • 提供reset()成员函数,将自身指针对象地址设为NULL,并将引用计数-1(当计数为0,会自动去delete内存)
  • 提供use_count()成员函数,可以用来查看引用计数个数,比如:
  shared_ptr<int> sp1(new int());      //计数+1
  cout<<sp1.use_count()<<endl; //打印计数:1
  cout<<sp1.unique()<<endl; //打印:1
     shared_ptr<int> sp2(sp1); //计数+1
  cout<<sp1.use_count()<<endl; //打印:2
  cout<<sp1.unique()<<endl; //由于sp1指针对象被sp2引用,打印:0   sp1.reset(); //将sp1指针对象地址设为NULL,计数-1   cout<<sp1.get()<<endl; //sp1指针对象地址为NULL,打印:0   cout<<sp2.use_count()<<endl; //打印:1   cout<<sp2.unique()<<endl; //由于sp1释放,仅剩下sp2指向30所在的地址,所以打印:1

初探shared_ptr智能指针(以上个Test类为例分析)

#include <iostream>
#include <memory> using namespace std; class Test
{
public:
int mvalue;
Test(int i=)
{
mvalue=i;
cout<< "Test("<<mvalue<<")"<<endl;
} ~Test()
{
cout<< "~Test("<<mvalue<<")"<<endl;
}
}; int main()
{
cout<<"*****begin*****"<<endl; shared_ptr<Test> p1(new Test());
shared_ptr<Test> p2(p1); cout<<"*p1="<< p1->mvalue<<","<<"*p2="<<p2->mvalue<<endl; p1.reset();
p2.reset(); cout<<"count:"<<p2.use_count()<<endl; cout<<"*****end*****"<<endl;
return ;
}

运行打印:

*****begin*****
Test()
*p1=, *p2=
~Test()
count:
*****end*****

从结果可以看到,我们把p1和p2都释放了后,由于count=0,便自动去delete Test指针了.

STL中的其它智能指针(在后面学习到,再来深入描述)

可以通过T *data()成员函数来获取指向的地址

-weak_ptr

  • 配合shared_ptr而引入的一种智能指针

-unique_ptr

  • 只能一个指针对象指向一片内存空间(和auto_ptr类似),但是不能被拷贝和赋值(实现唯一性)

QT中的智能指针

-QPointer 

  • 当其指向的对象被销毁时,本身会自动赋值为NULL(从而避免被多次释放和野指针)
  • 缺点在于,该模板类析构时,不会自动摧毁所指向的对象(需要手工delete)

-QSharedPointer 

  • 带有引用计数机制,支持多个指针对象指向同一片内存(实现共享)
  • 可以被自由地拷贝和赋值
  • 当引用计数为0(最后一个指针被摧毁)时,才删除指向的对象(和shared_ptr类似)

-QScopedPointer 

  • 优点在于生命期结束后会自动删除它所指的对象(不需要手工delete)
  • 不支持多个QScopedPointer指针对象指向同一片内存(不能共享)

示例:

    QScopedPointer<QPushButton>  p1(new QPushButton);

27.C++- 智能指针的更多相关文章

  1. 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr

    auto_ptr<string> p1(new string ("auto") : //#1 auto_ptr<string> p2; //#2 p2 = ...

  2. C++解析(27):数组、智能指针与单例类模板

    0.目录 1.数组类模板 1.1 类模板高效率求和 1.2 数组类模板 1.3 堆数组类模板 2.智能指针类模板 2.1 使用智能指针 2.2 智能指针类模板 3.单例类模板 3.1 实现单例模式 3 ...

  3. Linux 内核里的“智能指针”【转】

    转自:http://blog.jobbole.com/88279/ 众所周知,C/C++语言本身并不支持垃圾回收机制,虽然语言本身具有极高的灵活性,但是当遇到大型的项目时,繁琐的内存管理往往让人痛苦异 ...

  4. C++智能指针shared_ptr

    shared_ptr 这里有一个你在标准库中找不到的—引用数智能指针.大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章.最重要的一个细节是引用数是如何被执行的—插入,意思是说你将引 ...

  5. ZT自老罗的博客 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析

    Android系统的智能指针(轻量级指针.强指针和弱指针)的实现原理分析 分类: Android 2011-09-23 00:59 31568人阅读 评论(42) 收藏 举报 androidclass ...

  6. 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

    一.boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源.关于RAII的讨论可以参考前面的文章.在使 ...

  7. C++ 智能指针学习

     C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...

  8. (转)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现

     转载:http://www.cnblogs.com/felixYeou/archive/2008/08/27/1277250.html 快速导航 一. 回顾历史二. 智能指针简介三. Delphi中 ...

  9. Qt中容器类应该如何存储对象(最好使用对象指针类型,如:QList<TestObj*>,而不要使用 QList<TestObj> 这样的定义,建议采用 智能指针QSharedPointer)

    Qt提供了丰富的容器类型,如:QList.QVector.QMap等等.详细的使用方法可以参考官方文档,网上也有很多示例文章,不过大部分文章的举例都是使用基础类型:如int.QString等.如果我们 ...

随机推荐

  1. 基于netcore实现mongodb和ElasticSearch之间的数据实时同步的工具(Mongo2Es)

    基于netcore实现mongodb和ElasticSearch之间的数据实时同步的工具 支持一对一,一对多,多对一和多对多的数据传输方式. 一对一 - 一个mongodb的collection对应一 ...

  2. iframe标签的定时刷新

    由于有个项目是大数据类型的,需要时时展现数据,这就出现了这个需求,页面不断刷新,这个其实很简单了,window.location.reload(); 这个就轻松搞定了,但是灵机一动,加上个控制吧,这下 ...

  3. Linux 新手应该知道的一些求助命令

    Linux 真正的强大所在是他的[命令行].每一个 Linux 命令其实就是一个程序,借助这些命令,我们可以办到非常多的事情.遇到困难时应该用什么命令去解决呢?下面兄弟连教育Linux小编将会为大家介 ...

  4. 使用CoreRT将.NET Core发布为Native应用程序

    在上一篇文章<使用.NET Core快速开发一个较正规的命令行应用程序>中我们看到了使用自包含方式发布的.NET Core应用中包含了216个文件.我就写一个cat命令用得着这么动真格.. ...

  5. 【node】安装和配置node项目文件

    需要把 views文件中的子文件全部改为以 .ejs的后缀 1·npm install express -g (全局安装) 2·npm install -g express-generator (安装 ...

  6. 【Python】 如何用pyinstaller打包python程序成exe

    [pyinstaller] pyinstaller在他们的官方网站上下载:http://www.pyinstaller.org/ 下载完pyinstaller之后还要安装一个支持包pywin32. 这 ...

  7. Android学习笔记1——开发环境配置

    一.JDK配置 Android是基于Java进行开发的,首先需要在电脑上配置JDK(Java Development Kit).在http://www.androiddevtools.cn/下载对应系 ...

  8. 在用jQuery时遇到的小问题

    1. class类名问题? 在我在class ='看看(2)' ,凡是这样的居然给自身加其他style样式,居然添加不上,后来改成其他类名不带括号里的,居然好了. 2. line-height 引入的 ...

  9. 设计模式 --> (6)原型模式

    原型(Prototype)模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知 ...

  10. [luogu2831][noip d2t3]愤怒的小鸟_状压dp

    愤怒的小鸟 noip-d2t3 luogu-2831 题目大意:给你n个点,问最少需要多少条经过原点的抛物线将其覆盖. 注释:1<=点数<=18,1<=数据组数<=30.且规定 ...