auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
C ++库提供以下类型的智能指针的实现:
- auto_ptr
- unique_ptr
- shared_ptr
- weak_ptr
它们都是在内存头文件中声明。
auto_ptr
从C ++ 11开始,此类模板已被弃用。 unique_ptr是具有相似功能但具有改进的安全性的新工具。
auto_ptr是一个智能指针,用于管理通过新表达式获取的对象,并在auto_ptr本身被销毁时删除该对象。
当使用auto_ptr类描述一个对象时,它存储一个指向单个分配对象的指针,该对象可以确保当它超出范围时,它指向的对象必须被自动销毁。 它基于独占所有权模式,即同一类型的两个指针不能同时指向相同的资源。 如下面的程序所示,复制或分配指针会更改所有权,即源指针必须赋予目标指针所有权。
#include<iostream> #include<memory> using namespace std; class A { public: void show() { cout << "A::show()" << endl; } }; int main() { // p1 is an auto_ptr of type A auto_ptr<A> p1(new A); p1 -> show(); // returns the memory address of p1 cout << p1.get() << endl; // copy constructor called, this makes p1 empty. auto_ptr <A> p2(p1); p2 -> show(); // p1 is empty now cout << p1.get() << endl; // p1 gets copied in p2 cout<< p2.get() << endl; return 0; }
Output:
A::show() 0x1b42c20 A::show() 0 0x1b42c20
auto_ptr的拷贝构造函数和赋值运算符实际上并没有复制存储的指针,而是将它们传输出去,使第一个auto_ptr对象变为空。 这是实现严格所有权的一种方法,因此只有一个auto_ptr对象可以在任何给定时间拥有该指针,即在需要复制语义的情况下不应使用auto_ptr。
unique_ptr
std :: unique_ptr是在C ++ 11中开发的,用于替代std :: auto_ptr。unique_ptr是具有类似功能的新工具,但具有改进的安全性(无假拷贝分配),添加功能(删除器)和数组支持。 它是一个原始指针的容器。 它明确地防止复制其包含的指针,正如正常赋值那样会发生,即它只允许底层指针的一个所有者。
所以,当使用unique_ptr时,在任何一个资源上最多只能有一个unique_ptr,当该unique_ptr被破坏时,该资源将被自动声明。 另外,由于任何资源只能有一个unique_ptr,所以任何创建unique_ptr副本的尝试将导致编译时错误。
unique_ptr<A> ptr1 (new A); // Error: can't copy unique_ptr unique_ptr<A> ptr2 = ptr1;
但是,unique_ptr可以使用新的语义,即使用std :: move()函数将包含的指针的所有权转移到另一个unique_ptr。
// Works, resource now stored in ptr2 unique_ptr<A> ptr2 = move(ptr1);
所以,最好使用unique_ptr,当我们想要一个指向一个对象的指针,当该单个指针被销毁时将被回收。
// C++ program to illustrate the use of unique_ptr #include<iostream> #include<memory> using namespace std; class A { public: void show() { cout<<"A::show()"<<endl; } }; int main() { unique_ptr<A> p1 (new A); p1 -> show(); // returns the memory address of p1 cout << p1.get() << endl; // transfers ownership to p2 unique_ptr<A> p2 = move(p1); p2 -> show(); cout << p1.get() << endl; cout << p2.get() << endl; // transfers ownership to p3 unique_ptr<A> p3 = move (p2); p3->show(); cout << p1.get() << endl; cout << p2.get() << endl; cout << p3.get() << endl; return 0; }
Output:
A::show() 0x1c4ac20 A::show() 0 // NULL 0x1c4ac20 A::show() 0 // NULL 0 // NULL 0x1c4ac20
下面的代码返回一个资源,如果我们没有显式捕获返回值,资源将被清除。 如果我们这样做,那么我们拥有该资源的独占所有权, 这样我们可以将unique_ptr看作更安全,更好的替换auto_ptr。
unique_ptr<A> fun() { unique_ptr<A> ptr(new A); /* ... ... */ return ptr; }
何时使用unique_ptr?
当您想拥有资源的唯一所有权(Exclusive)时,请使用unique_ptr, 只有一个unique_ptr可以指向一个资源, 因为单个资源可以有一个unique_ptr,所以不可能将一个unique_ptr复制到另一个。
shared_ptr
引用计数:这是一种将资源数量,指针或句柄存入资源(如对象,内存块,磁盘空间或其他资源)的技术。
引用计数大于0,直到所有的shared_ptr副本都被删除,所包含的原始指针引用的对象将不会被销毁。因此,当我们要为一个原始指针分配给多个所有者时,我们应该使用shared_ptr。
#include<iostream> #include<memory> using namespace std; class A { public: void show() { cout<<"A::show()"<<endl; } }; int main() { shared_ptr<A> p1 (new A); cout << p1.get() << endl; p1->show(); shared_ptr<A> p2 (p1); p2->show(); cout << p1.get() << endl; cout << p2.get() << endl; // Returns the number of shared_ptr objects //referring to the same managed object. cout << p1.use_count() << endl; cout << p2.use_count() << endl; // Relinquishes ownership of p1 on the object //and pointer becomes NULL p1.reset(); cout << p1.get() << endl; cout << p2.use_count() << endl; cout << p2.get() << endl; return 0; }
Output:
0x1c41c20 A::show() A::show() 0x1c41c20 0x1c41c20 2 2 0 // NULL 1 0x1c41c20
何时使用shared_ptr?
如果要共享资源的所有权,请使用shared_ptr。 很多shared_ptr可以指向单个资源。 shared_ptr维护这个引用计数,当所有shared_ptr指向资源超出范围时,资源被破坏。
weak_ptr
循环依赖(shared_ptr的问题):让我们考虑一个场景,我们有两个类A和B,它们都有指向其他类的指针。 所以,它总是像A指向B和B指向A.因此,use_count永远不会达到零,并且永远不会被删除。
什么时候使用weak_ptr?
当你想要从多个地方引用你的对象 - 对于那些可以忽略和释放它们的引用(所以当你尝试取消引用时,它们只会注意到对象已经不见了)。
auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解的更多相关文章
- stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结
stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...
- C++11 weak_ptr智能指针
和 shared_ptr.unique_ptr 类型指针一样,weak_ptr 智能指针也是以模板类的方式实现的.weak_ptr<T>( T 为指针所指数据的类型)定义在<memo ...
- C++智能指针 auto_ptr、shared_ptr、weak_ptr和unique_ptr
手写代码是理解C++的最好办法,以几个例子说明C++四个智能指针的用法,转载请注明出处. 一.auto_ptr auto_ptr这是C++98标准下的智能指针,现在常常已经被C++标准的其他智能指针取 ...
- 聊聊智能指针 auto_ptr、shared_ptr、weak_ptr和unique_ptr
本文为转载:https://www.cnblogs.com/zeppelin5/p/10083597.html,对作者有些地方做了修正. 手写代码是理解C++的最好办法,以几个例子说明C++四个智能指 ...
- 第21课 shared_ptr共享型智能指针
一. shared_ptr的基本用法 (一)与unique_ptr的比较 比较 shared_ptr unique_ptr 备注 初始化 ①shared_ptr<T> sp; sp.res ...
- auto_ptr,unique_ptr,shared_ptr,weak_ptr
http://mojijs.com/2016/08/218129/index.html http://www.cnblogs.com/lanxuezaipiao/p/4132096.html
- 33.unique_ptr独享内存智能指针
#include <iostream> #include <memory> #include <string> #include <vector> us ...
- auto_ptr与shared_ptr ZZ
http://blog.csdn.net/rogeryi/article/details/1442700 Part(1) 这篇文章试图说明如何使用auto_ptr和shared_ptr,从而使得动态分 ...
- c++智能指针(unique_ptr 、shared_ptr、weak_ptr、auto_ptr)
一.前序 什么是智能指针? ——是一个类,用来存储指针(指向动态分配对象也就是堆中对象的的指针). c++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写 ...
随机推荐
- python16_day14【jQuery】
一.作用域 1.作用域例一 <script> var str = "global"; //AO1 AO1.str function t(age){ console.lo ...
- python 2 和python 3的 区别
用户交互 input ps:python2:raw_input python3:input 在 python2里 print不需要加括号也可以打印 子python3里 print 必须加括号才能打印
- JAVA接口中不可以有静态方法吗
1. 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错),所以不能含有静态代码块以及静态方法(用 ...
- Microservice 概念
一天我司招财猫姐(HR 大人)问我,你给我解释一下 Microservice 是什么吧.故成此文.一切都是从一个创业公司开始的. 故事 最近的创业潮非常火爆,我禁不住诱惑也掺和了进去,创建了一家公司. ...
- Qios RibbonForm QRibbonCaption添加qRibbonApplicationButton无法最大化问题
winform 用了Qios DevSuite系列的控件. RibbonForm中QRibbonCaption添加qRibbonApplicationButton之后无法最大化. 修改qRibbonA ...
- 【学习ffmpeg】打开视频文件,帧分析,并bmp保存关键帧
http://www.tuicool.com/articles/jiUzua http://blog.csdn.net/code_future/article/details/8646717 主题 ...
- less预编译语言使用总结
以前就使用过less和sass,其实很简单,就是很长时间不用,忘记语法了,现在来总结一片使用技巧 一.注释 less的注释不会被编译到css文件中,所以提倡多使用less中的注释:/**/ 二.变量 ...
- shell自动化一键部署脚本,秒级一键回滚脚本
#!/bin/bash # Node List PRE_LIST="192.168.222.163" # 预生产环境节点 GROUP1_LIST= ROLLBACK_LIST=&q ...
- MySQL-checkpoint技术
几个知识点: 缓冲池:缓存磁盘数据,通过内存速度弥补CPU速度和磁盘速度的鸿沟. 脏页:LRU列表中被修改的页,和磁盘上的数据不一致 刷新频率:每次有脏页就刷新,开销很大.需要一种刷新机制 数据丢失: ...
- Git服务器的Gitosis安装配置及gitignore的使用方法
Git服务器Gitosis安装设置 1.安装 openssh服务器 sudo apt-get install openssh-server openssh-client 2.创建个人公钥和私钥 在默认 ...