C++智能指针总结二——unique_ptr_unique_ptr赋值-程序员宅基地

技术标签: C/C++  c++  

1.往期回顾

C++智能指针总结一——auto_ptr

2.auto_ptr的缺陷

1.缺陷一

先来看下面的代码:

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

class DEMO {
    

public:

    DEMO(int data) {
    

        this->data = data;
        cout << "创建text" << endl;
        cout << "data=" << data << endl;
    }

    ~DEMO() {
    

        cout << "析构text" << endl;
        cout << "data=" << data << endl;
    }

private:
    int data;
};

int main(void) {
    

    auto_ptr<int> ptr(new int);
    auto_ptr<DEMO> ptr1(new DEMO(1));
    auto_ptr<DEMO> ptr2(new DEMO(2));

    cout << endl;
    cout << "ptr2=" << ptr2.get() << endl; //ptr2=ptr1之前
    cout << "ptr1=" << ptr1.get() << endl;
    ptr2 = ptr1;                           //将ptr1赋值给ptr2
    cout << "ptr2=" << ptr2.get() << endl; //ptr2=ptr1之后
    cout << "ptr1=" << ptr1.get() << endl;

    system("pause");

    return 0;
}

运行结果如下图:

在这里插入图片描述

使用.get()方法获取智能指针绑定的动态内存首地址。

为什么会这样呢,这是因为auto_ptr具有排他所有权性,即一块动态内存只能被一个智能指针绑定,所以在执行ptr2=ptr1之后就相当于把ptr1绑定的动态内存交给ptr2控制,但ptr2之前绑定了动态内存,所以它会先把自己绑定的动态内存先释放(delete掉),然后绑定ptr1的动态内存,最后ptr1的内置指针变量被置为空指针。

这种行为其实是很奇怪的,因为在我们之前的语法中赋值操作都不会产生如此怪异的行为。因此如果我们以往的思维方式去使用智能指针赋值操作就很可能产生你无法轻易察觉的错误。

2.缺陷二

不支持对象数组的内存管理

即不能使用auto_ptr指针分配数组,如:

在这里插入图片描述

3.unique_ptr

1.“更安全的赋值”

由于auto_ptr存在的种种缺陷,C++11标准使用新的,更安全的unique_ptr取代auto_ptr。

unique_ptr具有与auto_ptr一样的排他所有权性,同一块动态内存也只允许一个智能指针对象绑定。

但是unique_ptr不允许这样的直接赋值。

在这里插入图片描述

只能这样使用:

在这里插入图片描述
加一个move相当于向编译器声明你知道这样操作的风险和后果。实际上这样使用和auto_ptr的直接赋值也没有区别了,只是多了一个move提醒你自己智能指针赋值的特殊性。

2.支持创建动态数组

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

int main(void) {
    

    unique_ptr<int []> ptr1(new int[5]);     //分配动态数组
    
    for (int count = 0; count < 5; ++count) {
    
        ptr1[count] = count;
    }

    for (int count = 0; count < 5; ++count) {
    
        cout << "ptr1[" << count << "]=" << ptr1[count] << endl;
    }

    system("pause");

    return 0;
}

结果:

在这里插入图片描述

3.补充API

.release().reset() 方法和auto_ptr是一样的。详情可参考我的上一篇博文。这里主要讲一下新的。

.swap()方法:

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

int main(void) {
    

    unique_ptr<int []> ptr1(new int[5]);
    unique_ptr<int []> ptr2(new int[5]);
    
   
    cout << "ptr2=" << ptr2.get() << endl; 
    cout << "ptr1=" << ptr1.get() << endl;
    
    ptr1.swap(ptr2);      //交换两个智能指针绑定的动态内存
    cout << endl;

    cout << "ptr2=" << ptr2.get() << endl; 
    cout << "ptr1=" << ptr1.get() << endl;

    system("pause");

    return 0;
}

结果:

在这里插入图片描述
功能即交换两个智能指针绑定的动态内存。

主动释放对象:

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

int main(void) {
    

    unique_ptr<int []> ptr1(new int[5]);
    unique_ptr<int []> ptr2(new int[5]);
    
    cout << "ptr2=" << ptr2.get() << endl; 
    cout << "ptr1=" << ptr1.get() << endl;
                    
    ptr1 = nullptr;
    ptr2 = NULL;

    cout << "ptr2=" << ptr2.get() << endl; 
    cout << "ptr1=" << ptr1.get() << endl;
    

    system("pause");

    return 0;
}

结果:

在这里插入图片描述

底层源码:

 unique_ptr& operator=(nullptr_t) noexcept {
    
        reset();
        return *this;
    }

可以看到,unique_ptr重载了“=”号运算符,执行reset()函数,且注意到当reset()函数传入的参数为空时,参数默认初始化为nullptr,即能达到的效果为释放原先绑定的动态内存,再将对象指针赋值为nullptr。

reset()函数:

void reset(_Ty* _Ptr = nullptr) noexcept {
     // destroy designated object and store new pointer
        if (_Ptr != _Myptr) {
    
            delete _Myptr;
        }

        _Myptr = _Ptr;
    }

4.后续篇章

C++智能指针总结三——shared_ptr与weak_ptr

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45738899/article/details/121617633

智能推荐

webhooks是什么啊?有什么好处?_wedhook-程序员宅基地

文章浏览阅读387次。你需要向视频处理服务器上传一个视频、你需要获得视频处理后的结果,然而视频处理服务器上视频很多,在排队进行处理,你不能立刻获取到视频的处理结果,此时你可以设计一个hook url,当视频处理完成后,视频处理服务器自动向你的hook url发送请求,告诉你视频已经处理完毕.在传统的web server设计中,我们项目A想要获取项目B的数据,通常项目B需要提供一个API,然后项目A去请求项目B的API,从而获得数据,这样的过程我们称之为"拉"数据。==通过webhook机制,对客户端-服务端的模式进行了逆转。_wedhook

解决:Error:java xxxx 程序包不存在_java语言unil程序包不存在什么意思-程序员宅基地

文章浏览阅读3.2w次,点赞8次,收藏9次。今天早上,一跑项目报错了。。java程序包不存在。我是小白啊,之前没有遇到过这种问题就赶紧查了查。终于解决了。其实我遇到的也不是什么大问题,只是该文件下少了上述的jar包(见下图)。再查看 pom 文件没有报错,和 Maven Projects 中的 Dependencies 中都没有缺少这些内容。直接重新导入全部的Maven Projects 就好了。参考文章:..._java语言unil程序包不存在什么意思

java接收ajax传参_Ajax传值以及接受传值,@ResPonseBody 和 @RequestBody-程序员宅基地

文章浏览阅读873次。Ajax对于Java编程人员开说可是很重要的,可以说是必会的。Title// 第二步:使用Jquery的 ajax (被封装过的)来请求数据地址$.ajax({type:'post',url:'api/data.json',data:{},success:function (res) {console.log(res)}})// url: 填写的内容的是 后台的数据接口// type: 本次发送..._java控制层获取ajax传参

【Python】 将一个函数作为参数传递到另一个函数中_python怎么作为参数引入一个方程-程序员宅基地

文章浏览阅读2.6k次,点赞3次,收藏2次。背景:学数据结构的时候需要一个能够测量各种算法消耗时长的函数,重复写,话不多说直接上代码。import time as tdef mutinomial(n,a,x): p = 0 for i in range(0,n+1): p += a[i]*pow(x,i) return print(p)def qinjiushao(n,a,x): p = a[n] for i in range(n,0,-1): p *= x _python怎么作为参数引入一个方程

你训练的神经网络不对头的37个原因-程序员宅基地

文章浏览阅读403次。点击上方“AI公园”,关注公众号,选择加“星标“或“置顶”作者:Slav Ivanov编译:ronghuaiyang导读大家都遇到过这种情况,训练的时候没什么问题,测试的..._神经网络错误直方图的instance

学计算机免修考试,长沙学院非计算机专业学生计算机基础课程免修实施办法-程序员宅基地

文章浏览阅读879次。长大教〔2018〕145号计算机基础课程是非计算机专业人才培养中的基础性课程,是当代大学生必须掌握的基础知识和基本能力。为贯彻因材施教的原则,突出个性化教学的要求,提高教学效率,根据《长沙学院课程考核管理办法》(长大发〔2017〕42号)的精神,经学校研究,决定对非计算机专业学生计算机基础课程作以下免修规定。一、免修的课程非计算机专业的计算机基础课程包括第一学期开设的《大学计算机基础》课程,第二学..._大学计算机免修的条件

随便推点

爬虫逆向学习进阶路线_爬虫逆向进阶pdf下载-程序员宅基地

文章浏览阅读1.2w次,点赞46次,收藏241次。大数据时代下,爬虫技术逐渐成为一套完整的系统性工程技术,涉及的知识面广,平台多,技术越来越多样化,对抗性也日益显著。大家可以参考一下学习路线,看看自己需要对哪些知识进行补充。爬虫逆向学习路线学习路线总结系统提高加密算法特征和实现传输协议和通讯协议各种验证码识别方法个人汇总专栏爬虫逆向社区学习路线总结基础学习路线总结:主语言基础语法常用网络请求库、解析库常用抓包工具自动化工具库流行采集框架多进程、多线程、协程、分布式爬虫采集器管理Js逆向学习路线总结:浏览器构造、基础语法、作_爬虫逆向进阶pdf下载

IT各个领域推荐的书籍-程序员宅基地

文章浏览阅读119次。1、C语言提升《c和指针》《c缺陷和陷阱》《c专家编程》这三本书我在很多的文章中都提过,是一个初级C程序员必看的三本书,同时也是我们公司应届新员工必须好好学习的教材,非常适合刚毕业的大学生学习。2、C++语言提升Effective C++:改善程序与设计的55个具体做法》《More EffectiveC++:35个..._反模式:危机中软件、架构和项目的重构

Comsol事件控制线圈加热冷却(涡流热成像)_comsol涡流检测里线圈-程序员宅基地

文章浏览阅读1.1k次,点赞19次,收藏12次。在涡流加热过程中,通常需要关注的不仅是加热过程,还有加热物体的冷却过程。这非常重要。Xiao XT【】中用试验方法说明了对于缺陷的深度的定量分析,加热与冷却过程的频域图(幅度与相位)十分重要。_comsol涡流检测里线圈

Java——《面试题——MySQL篇》_java mysql面试题-程序员宅基地

文章浏览阅读3.3k次,点赞4次,收藏28次。视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是 有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易, 相比多表查询。内联接(Inner Join):匹配2张表中相关联的记录。左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记 录,右表中未匹配到的字段用NULL表示。_java mysql面试题

web3j 命令行_web3j 命令行工具-程序员宅基地

文章浏览阅读7.8k次。1. 下载最新的版本已经没有直接的命令行工具了,工具版本v4.5.5 下载2. 可以配置到环境变量3. 命令version: 版本号wallet: create: 生成一个新的以太坊钱包 update:更新现有钱包的密码 send: 将以太币发送到另一个地址solidity: 智能合约new:import:..._web3j 命令行工具

iptables移植到ARM Linux教程_arm-linux iptable源码下载-程序员宅基地

文章浏览阅读5.1k次,点赞5次,收藏10次。http://www.veryarm.com/568.htmliptables或netfilter(网络过滤器)是一个工作于用户空间的防火墙应用软件,允许系统管理员可以调整设置X表(Xtables)提供相关的系统表格(目前主要位于iptables/netfilter)以及相关的“链”与“规则”,以管理网络数据包的流动与转送的动作。Iptables是用户态提供的更改过滤规_arm-linux iptable源码下载

推荐文章

热门文章

相关标签