c++——智能指针学习(unique_ptr)

时间:2022-10-25 18:30:04

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 有两个版本:

1) 管理个对象(例如以 new 分配)
2) 管理动态分配的对象数组(例如以 new[] 分配)

类满足可移动构造 (MoveConstructible) 和可移动赋值 (MoveAssignable) 的要求,但不满足可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的要求。

总结起来就是:=或者reset都会转移unique_ptr的控制权,并调用析构函数。

c++——智能指针学习(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)的更多相关文章

  1. 深入学习c&plus;&plus;--智能指针&lpar;三&rpar; unique&lowbar;ptr

    1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...

  2. Qt 智能指针学习(7种指针)

    Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...

  3. 智能指针&lpar;三&rpar;&colon;unique&lowbar;ptr使用简介

    我们知道auto_ptr通过复制构造或者通过=赋值后,原来的auto_ptr对象就报废了.所有权转移到新的对象中去了.而通过shared_ptr可以让多个智能指针对象同时拥有某一块内存的访问权.但假如 ...

  4. &lbrack;转&rsqb; 智能指针&lpar;三&rpar;&colon;unique&lowbar;ptr使用简介

    PS: 1. auto_ptr太不安全,可能多个auto_ptr指向一个对象,出现重复释放的问题 2. unique_ptr解决了这个问题,不允许拷贝构造函数和赋值操作符,但是!它支持移动构造函数,通 ...

  5. Qt 智能指针学习(7种QT的特有指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  6. Qt 智能指针学习(7种QT智能指针和4种std智能指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  7. Qt 智能指针学习

    原地址:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include & ...

  8. &lbrack;转&rsqb;Qt 智能指针学习

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  9. 智能指针之 unique&lowbar;ptr

    对于动态申请的内存,C++语言为我们提供了new和delete运算符, 而没有像java一样,提供一个完整的GC机制,因此对于我们申请的动态内存, 我们需要时刻记得释放,且不能重复释放,释放后不能再去 ...

随机推荐

  1. C&num;面向对象学习笔记概要

    1.面向对象不是取代面向过程的. 2.面向对象的三个特性:封装.继承.多态. 3.字段.方法.属性(后面讲)都可以叫做类的成员,他们都需要定义访问级别.访问级别的用处在于控制成员在哪些地方可以被访问, ...

  2. HW4&period;20

    public class Solution { public static void main(String[] args) { boolean isPrime = true; int count = ...

  3. linux 下信号处理命令trap &amp&semi;&amp&semi; linux下各种信号的意义

    1.用途说明 trap是一个shell内建命令,它用来在脚本中指定信号如何处理.比如,按Ctrl+C会使脚本终止执行,实际上系统发送了SIGINT信号给脚本进程,SIGINT信号的默认处理方式就是退出 ...

  4. 武汉科技大学ACM :1003&colon; 零起点学算法78——牛牛

    Problem Description 牛牛是一种纸牌游戏,总共5张牌,规则如下: 如果找不到3张牌的点数之和是10的倍数,则为没牛: 如果其中3张牌的点数之和是10的倍数,则为有牛,剩下两张牌的点数 ...

  5. 8&period;DNS :域名系统

    前面已经提到了访问一台机器要靠IP地址和MAC地址,其中,MAC地址可以通过ARP协议得到,所以这对用户是透明的,但是IP地址就不行,无论如何用户都需要用一个指定的IP来访问一台计算机,而IP地址又非 ...

  6. Unity User Group 北京站图文报道:《Unity虚拟现实实战技巧》

    时间来到了盛夏,北京UUG活动也来到了第八期.本次活动的主题为<Unity虚拟现实实战技巧>,为此我们邀请了4位资深的行业大神.这次我们仍然在北京市海淀区丹棱街5号微软大厦举行活动,在这里 ...

  7. 关于EF中出现FOREIGNKEY约束可能会导致循环或多重级联路径的问题

    ef中,我们创建外键的时候需要注意,否则会出现标题所示问题. 例:有项目表,项目收藏表,用户表 项目表有如下字段:ProjectId,InputPersonId等 项目收藏表有如下字段:Project ...

  8. android&colon; 接收系统广播

    Android 内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到 各种系统的状态信息.比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一 条广播,时间或时区发生改变也会发 ...

  9. &lbrack;6&rsqb; 胶囊体&lpar;Capsule&rpar;图形的生成算法

    顶点数据的生成 bool YfBuildCapsuleVertices ( Yreal radius, Yreal height, Yuint slices, Yuint stacks, YeOrig ...

  10. 11&lowbar;java之接口和多态

    01接口的概念 * A:接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”. 接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来 ...