广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++智能指针hared_ptr与右值引用的方法
  • 273
分享到

C++智能指针hared_ptr与右值引用的方法

2023-06-20 15:06:37 273人浏览 独家记忆
摘要

本篇内容主要讲解“c++智能指针hared_ptr与右值引用的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++智能指针hared_ptr与右值引用的方法”吧!目录 介绍 初始化方法1 通

本篇内容主要讲解“c++智能指针hared_ptr与右值引用的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++智能指针hared_ptr与右值引用的方法”吧!

目录
  • 介绍

  • 初始化方法

    • 1 通过构造函数初始化

    • 2 通过拷贝和移动构造函数初始化

    • 3 通过 std::make_shared 初始化

    • 4 通过 reset 方法初始化

  • 获取原始指针

    • 指定删除器

      • 参考链接

        1. 介绍

        在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。

        C++11 中提供了三种智能指针,使用这些智能指针时需要引用头文件

        • std::shared_ptr:共享的智能指针

        • std::unique_ptr:独占的智能指针

        • std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视 shared_ptr 的。

        共享智能指针(shared_ptr)是指多个智能指针可以同时管理同一块有效的内存,共享智能指针 shared_ptr 是一个模板类,如果要进行初始化有三种方式:通过构造函数、std::make_shared 辅助函数以及 reset 方法。共享智能指针对象初始化完毕之后就指向了要管理的那块堆内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数 use_count

        2. 初始化方法

        2.1 通过构造函数初始化

        实例

        // 使用智能指针管理一块 int 型的堆内存shared_ptr<int> ptr1(new int(520));

        2.2 通过拷贝和移动构造函数初始化

        调用拷贝构造函数

        shared_ptr<int> ptr2(ptr1);

        调用移动构造函数

        std::shared_ptr<int> ptr5 = std::move(ptr2);

        如果使用拷贝的方式初始化共享智能指针对象,这两个对象会同时管理同一块堆内存,堆内存对应的引用计数也会增加;
        如果使用移动的方式初始智能指针对象,只是转让了内存的所有权,管理内存的对象并不会增加,因此内存的引用计数不会变化。

        2.1 移动构造

        关于移动构造,可能有些读者不太明白

        移动构造是C++11标准中提供的一种新的构造方法。

        在现实中有很多这样的例子,我们将钱从一个账号转移到另一个账号,将手机SIM卡转移到另一台手机,将文件从一个位置剪切到另一个位置……移动构造可以减少不必要的复制,带来性能上的提升。

        我们首先来看看move函数
        首先看这样一段代码

        #include <iOStream>#include <cstring>#include <cstdlib>#include <vector>using namespace std;int main(){string st = "I love 进击的汪sir";vector<string> vc;vc.push_back(move(st));cout << vc[0] << endl;if (!st.empty())cout << st << endl;return 0;}

        输出的结果为

        C++智能指针hared_ptr与右值引用的方法

        再看这样一段代码

        #include <iostream>#include <cstring>#include <cstdlib>#include <vector>using namespace std;int main(){string st = "I love xing";vector<string> vc;vc.push_back(st);cout << vc[0] << endl;if (!st.empty())cout << st << endl;return 0;}

        其结果为

        C++智能指针hared_ptr与右值引用的方法

        这两段代码唯一的不同是调用vc.push_back()将字符串插入到容器中去时,第一段代码使用了move语句,而第二段代码没有使用move语句。输出的结果差异也很明显,第一段代码中,原来的字符串st已经为空,而第二段代码中,原来的字符串st的内容没有变化。

        先暂时记住这两端代码的输出结果之间的差异。
        我们回到移动构造函数上

        有时候我们会遇到这样一种情况,我们用对象a初始化对象b,后对象a我们就不在使用了,但是对象a的空间还在呀(在析构之前),既然拷贝构造函数,实际上就是把a对象的内容复制一份到b中,那么为什么我们不能直接使用a的空间呢?这样就避免了新的空间的分配,大大降低了构造的成本。这就是移动构造函数设计的初衷。

        通俗一点的解释就是,拷贝构造函数中,对于指针,我们一定要采用深层复制,而移动构造函数中,对于指针,我们采用浅层复制。

        所以在上面的例子中,如果调用移动构造函数来初始化智能指针,引用计数是不会增加的,而move函数实际上是返回的右值引用

        2.2 右值引用

        上面我们讲到了右值引用,这里就来扩展一下右值引用是啥
        首先得分清楚,什么是右值,什么是左值

        • lvalue 是 loactor value 的缩写,rvalue 是 read value 的缩写

        • 左值是指存储在内存中、有明确存储地址(可取地址)的数据;

        • 右值是指可以提供数据值的数据(不可取地址);

        通过描述可以看出,区分左值与右值的便捷方法是:可以对表达式取地址(&)就是左值,否则为右值 。所有有名字的变量或对象都是左值,而右值是匿名的。

        C++11 中右值可以分为两种:一个是将亡值( xvalue, expiring value),另一个则是纯右值( prvalue, PureRvalue):

        • 纯右值:非引用返回的临时变量、运算表达式产生的临时变量、原始字面量和 lambda 表达式等

        • 将亡值:与右值引用相关的表达式,比如,T&& 类型函数的返回值、 std::move 的返回值等。

        右值引用就是对一个右值进行引用的类型。因为右值是匿名的,所以我们只能通过引用的方式找到它。无论声明左值引用还是右值引用都必须立即进行初始化,因为引用类型本身并不拥有所绑定对象的内存,只是该对象的一个别名。通过右值引用的声明,该右值又“重获新生”,其生命周期与右值引用类型变量的生命周期一样,只要该变量还活着,该右值临时量将会一直存活下去。

        右值通过&&来引用

        例如:

        • int&& value = 520; 里面 520 是纯右值,value 是对字面量 520 这个右值的引用。

        • int &&a2 = a1; 中 a1 虽然写在了 = 右边,但是它仍然是一个左值,使用左值初始化一个右值引用类型是不合法的。

        • const Test& t = getObj() 这句代码的语法是正确的,常量左值引用是一个万能引用类型,它可以接受左值、右值、常量左值和常量右值。

        2.3 通过 std::make_shared 初始化

        通过 C++ 提供的 std::make_shared() 就可以完成内存对象的创建并将其初始化给智能指针,函数原型如下:

        template< class T, class... Args >shared_ptr<T> make_shared( Args&&... args );

        实例
        使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1

        shared_ptr<int> ptr1 = make_shared<int>(520);

        注意
        使用 std::make_shared() 模板函数可以完成内存地址的创建,并将最终得到的内存地址传递给共享智能指针对象管理。如果申请的内存是普通类型,通过函数的()可完成地址的初始化,如果要创建一个类对象,函数的()内部需要指定构造对象需要的参数,也就是类构造函数的参数。

        2.4 通过 reset 方法初始化

        共享智能指针类提供的 std::shared_ptr::reset 方法函数原型如下:

        void reset() noexcept;template< class Y >void reset( Y* ptr );template< class Y, class Deleter >void reset( Y* ptr, Deleter d );template< class Y, class Deleter, class Alloc >void reset( Y* ptr, Deleter d, Alloc alloc );
        • ptr:指向要取得所有权的对象的指针

        • d:指向要取得所有权的对象的指针

        • aloc:内部存储所用的分配器

        实例

        shared_ptr<int> ptr5;ptr5.reset(new int(250));

        3. 获取原始指针

        对应基础数据类型来说,通过操作智能指针和操作智能指针管理的内存效果是一样的,可以直接完成数据的读写。但是如果共享智能指针管理的是一个对象,那么就需要取出原始内存的地址再操作,可以调用共享智能指针类提供的 get () 方法得到原始地址,其函数原型如下:

        T* get() const noexcept;

        实例

        #include <iostream>#include <string>#include <memory>using namespace std;int main(){    int len = 128;    shared_ptr<char> ptr(new char[len]);    // 得到指针的原始地址    char* add = ptr.get();    memset(add, 0, len);    strcpy(add, "博客:进击的汪sir");    cout << "string: " << add << endl;        shared_ptr<int> p(new int);    *p = 100;    cout << *p.get() << "  " << *p << endl;        return 0;}

        4. 指定删除器

        当智能指针管理的内存对应的引用计数变为 0 的时候,这块内存就会被智能指针析构掉了。另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器,这个删除器函数本质是一个回调函数,我们只需要进行实现,其调用是由智能指针完成的。

        实例

        #include <iostream>#include <memory>using namespace std;// 自定义删除器函数,释放int型内存void deleteIntPtr(int* p){    delete p;    cout << "int 型内存被释放了...";}int main(){    shared_ptr<int> ptr(new int(250), deleteIntPtr);    return 0;}

        删除器函数也可以是 lambda 表达式!

        5. 参考链接

        https://subingwen.cn/cpp/shared_ptr/
        Https://www.cnblogs.com/qingergege/p/7607089.html

        到此,相信大家对“C++智能指针hared_ptr与右值引用的方法”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

        --结束END--

        本文标题: C++智能指针hared_ptr与右值引用的方法

        本文链接: https://www.lsjlt.com/news/297880.html(转载时请注明来源链接)

        有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

        本篇文章演示代码以及资料文档资料下载

        下载Word文档到电脑,方便收藏和打印~

        下载Word文档
        猜你喜欢
        • C++智能指针hared_ptr与右值引用的方法
          本篇内容主要讲解“C++智能指针hared_ptr与右值引用的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++智能指针hared_ptr与右值引用的方法”吧!目录 介绍 初始化方法1 通...
          99+
          2023-06-20
        • 深入学习C++智能指针之shared_ptr与右值引用的方法
          目录1. 介绍2. 初始化方法2.1 通过构造函数初始化2.2 通过拷贝和移动构造函数初始化2.3 通过 std::make_shared 初始化2.4 通过 reset 方法初始化...
          99+
          2022-11-12
        • C/C++中智能指针的用法详解
          目录前言一、什么是智能指针二、使用方法1.shared_ptr2.unique_ptr3.weak_ptr前言 本章主要介绍一些C/C++中智能指针的实现原理以及如何使用 一、什么是...
          99+
          2023-01-04
          C++智能指针使用 C++智能指针
        • C++11万能引用和右值引用的方法
          这篇文章主要介绍了C++11万能引用和右值引用的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++11万能引用和右值引用的方法文章都会有所收获,下面我们一起来看看吧。正文实际上,type&&...
          99+
          2023-06-29
        • 一文掌握 C++ 智能指针的使用方法
          目录一、RAII 与引用计数二、std::shared_ptr三、std::unique_ptr四、std::weak_ptr五、总结 一、RAII 与引用计数 了解 Objecti...
          99+
          2022-11-12
        • C++ STL 四种智能指针的用法详解
          目录0.前言1.unique_ptr2.auto_ptr3.shared_ptr 3.1 简介3.2 通过辅助类模拟实现 shared_ptr4.weak_ptr4.1 简...
          99+
          2022-11-12
        • C++11语法之右值引用的方法
          这篇文章主要讲解了“C++11语法之右值引用的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11语法之右值引用的方法”吧!一、{}的扩展在原先c++的基础上,C++11扩展了很多初...
          99+
          2023-06-29
        • C++中右值引用与移动语义的方法是什么
          今天小编给大家分享一下C++中右值引用与移动语义的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。意义充分利用临时对...
          99+
          2023-07-05
        • C++右值引用,移动语义与完美转发得方法
          本篇内容主要讲解“C++右值引用,移动语义与完美转发得方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++右值引用,移动语义与完美转发得方法”吧!C++&mdash;&mda...
          99+
          2023-06-29
        • C++中左值与右值的概念与应用方法是什么
          这篇文章主要讲解了“C++中左值与右值的概念与应用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中左值与右值的概念与应用方法是什么”吧!什么是左值与右值?左值(Lvalue)...
          99+
          2023-07-05
        • C++右值引用与移动构造函数应用的方法是什么
          这篇文章主要讲解了“C++右值引用与移动构造函数应用的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++右值引用与移动构造函数应用的方法是什么”吧!1.右值引用右值引用是 C++...
          99+
          2023-07-05
        • C语言简明分析指针与引用的具体用法
          目录1、指针2、引用1、指针 在计算机中,数据是存放在内存单元中的,一般把内存中的一个字节称为一个内存单元。为了更方便地访问这些内存单元,可预先给内存中的所有内存单元进行地址编号,根...
          99+
          2022-11-13
        • C++中指针问题及引用问题的解决方法
          C++中指针问题及引用问题的解决方法在C++编程中,指针是一种非常重要的数据类型,允许我们直接访问内存地址。然而,指针也经常会导致一些问题,例如空指针引用和悬空指针引用。此外,我们还经常会遇到引用问题,例如引用类型的函数参数传递和返回值引用...
          99+
          2023-10-22
          解决方法 指针问题 关键词: 引用问题
        • C++中指针问题和引用问题的解决方法
          C++中指针问题和引用问题的解决方法引言:在C++编程过程中,指针问题和引用问题是常见的困扰程序员的难题。本文将介绍一些解决这些问题的方法,并通过具体的代码示例进行说明,帮助读者更好地理解和应用。一、指针问题的解决方法空指针检测在使用指针之...
          99+
          2023-10-22
          指针问题解决方法:指针 引用问题解决方法:引用 C++中的解决方法:解决方法
        • C++11右值引用和移动语义的方法是什么
          本文小编为大家详细介绍“C++11右值引用和移动语义的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++11右值引用和移动语义的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。左值引用与右值...
          99+
          2023-07-05
        • C语言指针与引用的区别以及引用的三种用法案例详解
          1.指针与引用的区别: 指针是一块内存的地址值,而引用是一块内存的别名。 下面引自://www.jb51.net/article/221791.htm 从概念上讲。指针从本质上讲就是...
          99+
          2022-11-12
        • 进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持
          C++的编程精华,走过路过千万不要错过啊!废话少说,我们直接进入正题!!!! 函数高级 C++的函数提高 函数默认参数 在C++中,函数的形参列表中的形参是可以有默认值的。 语法:返回值类型 函数名 (参数 = 默认值){} 示例: #...
          99+
          2023-09-17
          c语言 c++ 开发语言 java 核心编程
        软考高级职称资格查询
        编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
        • 官方手机版

        • 微信公众号

        • 商务合作