c++——智能指针学习(unique_ptr)
1.为什么会有unique_ptr?
动态内存忘记delete,导致内存泄漏。比如:
p = new ();
if(...)
{
return ;
}
delete p;
因此我们需要一种方式来解决这个问题,不管我们怎么折腾,能够避免内存不释放的问题。
于是我们引入了auto_ptr,但是auto_ptr相对来说有以下缺点,目前已经停用了。
缺点1:
缺点2:
auto_ptr的进化版unique_ptr就被引入进来。
2.unique_ptr的特点。
unique_ptr继承了auto_ptr的部分优点,对缺点进行改进。
unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权,包括:
特点1 拥有它指向的对象
特点2 无法进行复制构造,无法进行复制赋值操作。即无法使两个unique_ptr指向同一个对象。但是可以进行移动构造和移动赋值操作
特点3 保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它指向的对象
这基本就满足我们某些场景下的需求了。
3.unique_ptr的使用
看代码
#include<iostream>
#include<memory>
class Mars
{
public:
~Mars ()
{
std::cout<<this<<"~Mars"<<std::endl;
}
void prin()
{
std::cout<<this<<",I am Mars"<<std::endl;
}
}; int main()
{
{
Mars* mars = new Mars;
std::unique_ptr<Mars> pMars(mars);
std::cout << "pMars->prin: ";
pMars->prin();
std::cout << "pMars.get()->prin: ";
pMars.get()->prin();
std::cout << "(*pMars).prin: ";
(*pMars).prin(); std::cout << "pMars:" << pMars.get() <<std::endl;
pMars.reset(new Mars);
std::cout << "pMars.reset.prin: ";
pMars->prin(); std::unique_ptr<Mars> pMars2;
pMars2 = std::move(pMars);
std::cout << "pMars2.move.prin: ";
std::cout << "pMars2:" << pMars2.get() << std::endl;
pMars2->prin();
} system("pause");
return ;
}
4.unique_ptr的官方文档
官方文档:
std::unique_ptr
是通过指针占有并管理另一对象,并在 unique_ptr
离开作用域时释放该对象的智能指针。
在下列两者之一发生时用关联的删除器释放对象:
销毁了管理的 unique_ptr
对象
通过 operator= 或 reset() 赋值另一指针给管理的 unique_ptr
对象。
通过调用 get_deleter()(ptr) ,用潜在为用户提供的删除器释放对象。默认删除器用 delete 运算符,它销毁对象并解分配内存。
unique_ptr
亦可以不占有对象,该情况下称它为空 (empty)。
std::unique_ptr
有两个版本:
类满足可移动构造 (MoveConstructible) 和可移动赋值 (MoveAssignable) 的要求,但不满足可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的要求。
总结起来就是:=或者reset都会转移unique_ptr的控制权,并调用析构函数。
我们注意到此处有一个make_unique的非成员函数。
一般来说,我们创建一个unique_ptr有两种方法
auto autoMars = std::make_unique<Mars>();//第一种
autoMars->prin();
Mars *mars = new Mars;//第二种
std::unique_ptr<Mars> pMars(mars);
为什么呢?
使用unique_ptr
并不能绝对地保证异常安全。看一个例子
func(unique_ptr<T>{ new T }, func_throw_exception());
在c++标准中,并没有规定参数运行调用的顺序,所以可能会出现以下调用顺序。
- new T
func_throw_exception
unique_ptr<T>
这样就导致,new出来的东西可能在抛异常之后无法回收!
func(make_unique<T>(), func_throw_exception()); //改成这样就可以避免上述问题。
参考文档如下,感谢!
官方文档:https://zh.cppreference.com/w/cpp/memory/unique_ptr
主要思路:http://senlinzhan.github.io/2015/04/20/%E8%B0%88%E8%B0%88C-%E7%9A%84%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/
demo思路:http://www.cnblogs.com/TenosDoIt/p/3456704.html
c++——智能指针学习(unique_ptr)的更多相关文章
- 深入学习c++--智能指针(三) unique_ptr
1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...
- Qt 智能指针学习(7种指针)
Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...
- 智能指针(三):unique_ptr使用简介
我们知道auto_ptr通过复制构造或者通过=赋值后,原来的auto_ptr对象就报废了.所有权转移到新的对象中去了.而通过shared_ptr可以让多个智能指针对象同时拥有某一块内存的访问权.但假如 ...
- [转] 智能指针(三):unique_ptr使用简介
PS: 1. auto_ptr太不安全,可能多个auto_ptr指向一个对象,出现重复释放的问题 2. unique_ptr解决了这个问题,不允许拷贝构造函数和赋值操作符,但是!它支持移动构造函数,通 ...
- Qt 智能指针学习(7种QT的特有指针)
从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...
- Qt 智能指针学习(7种QT智能指针和4种std智能指针)
从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...
- Qt 智能指针学习
原地址:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include & ...
- [转]Qt 智能指针学习
从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...
- 智能指针之 unique_ptr
对于动态申请的内存,C++语言为我们提供了new和delete运算符, 而没有像java一样,提供一个完整的GC机制,因此对于我们申请的动态内存, 我们需要时刻记得释放,且不能重复释放,释放后不能再去 ...
随机推荐
- Python收发邮件
发送邮件使用SMTP协议,接受POP3或IMAP: 创建邮件内容email模块,发送邮件smtplib模块.发送邮件比较简单,只需先创建SMTP对象,登录服务器后根据发收邮箱地址发送即可: POP3接 ...
- MongoDB基本命令总结
其实一直想整理下我常使用的MongoDB数据库的一些操作命令,终于有时间了~ MongoDB是一种开源的,免费的非关系型数据库(NoSql),不存在表.记录等概念,与通常的关系型数据库有些差异: Mo ...
- 【SoftwareTesting】Homework3
(a) (b) 数组越界问题 (c) n=0 (d) 点覆盖:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 边覆盖:[(1,2),(2,3),(3,4),(4,5) ...
- VMware Pro 14.1.2 官方正式版及激活密钥
热门虚拟机软件VMware Workstation Pro现已更新至14.1.2,14.0主要更新了诸多客户机操作系统版本,此外全面兼容Wind10创建者更新.12.0之后属于大型更新,专门为Win1 ...
- ForkJoinPool 源码
ForkJoinPool----FJP先看task.fork方法,含义是将当前任务,放到当前线程的工作队列中.但是第一次执行这个方法是在主线程中,主线程是不可能被FJP管理的.那么就进入ForkJoi ...
- js 获取字符串中所有的数字和汉字
var re1 = /(\d{1,3})+(?:\.\d+)?/g var re2 = /[\u4e00-\u9fa5]{2,}/g var str="11我22们33两个"; v ...
- 北大poj- 1007
DNA排序 逆序数可以用来描述一个序列混乱程度的量.例如,“DAABEC”的逆序数为5,其中D大于他右边的4个数,E大于他右边的1个数,4+1=5:又如,“ZWQM”的逆序数为3+2+1+0=6. 现 ...
- MAC Homebrew安装和简单使用
前言: 这个周六日在刚刚买的macbookpro(系统版本是:10.13.5)上面安装angular,一开始是按照windows上的顺序安装的,先安装node.js,然后在安装angular的时候报错 ...
- c++单链表冒泡排序(交换结点),链表增删改查,运算符重载
#include <iostream> #include <stdlib.h> #include <time.h> #include <fstream> ...
- 【温故知新】HTTP请求GET和POST的用法和区别
转自http://www.w3school.com.cn GET的使用 请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的: /test/demo_form.asp?name1=v ...