C++智能指针

2023-05-16

文章目录

  • 前言
  • shared_ptr
  • unique_ptr
  • weak_ptr
    • 使用智能指针安全吗?


前言

下面简单的概括了 3中智能指针的在使用时候需要注意的一些地方,三种智能指针在离开其作用域之后都会被自动释放,适合有一定基础。


提示:以下是本篇文章正文内容,下面案例可供参考

shared_ptr

shared_ptr使用注意点:

  • shared_ptr 不能通过“直接将原始这种赋值”来初始化,需要通过构造函数和辅助方法来初始化
#include <iostream>
using namespace std;

int main()
{
	//正确初始化方法
    std::shared_ptr<int> p1(new int(1));
    
	//错误的初始化方法-使用直接将原始这种赋值
	std::shared_ptr<int> p1 = new int(1);
}
  • 每次调用构造函数来初始化指针时,会引起引用计数加1
  • 每次调用构造函数来删除指针时,也会引起引用计数减1
#include <iostream>
using namespace std;

int main()
{
    std::shared_ptr<int> p1(new int(1));

    std::shared_ptr<int> p2(p1);
    
    //查看引用计数
    cout << "p1.use_count() = " << p1.use_count() << endl;
    cout << "p2.use_count() = " << p2.use_count() << endl;

    //调用构造删除删除 p2 指针
    p2.reset();

    //查看引用计数
    cout << "p1.use_count() = " << p1.use_count() << endl;
    cout << "p2.use_count() = " << p2.use_count() << endl;
}

  • 通过 get 方法来返回原始指针(不建议 (1)使用无论是保存为裸指针还是shared_ptr都是错的 (2)delete
    p.get()会造成一块内存delete两次))
#include <iostream>
using namespace std;


int main()
{
    std::shared_ptr<int> p1(new int(1));
	
	//错误示例:保持了裸指针且不小心删除了,会造成一块内存删除两次,程序卒
    int *p = p1.get();
    delete  p;
  • 不要用一个原始指针初始化多个shared_ptr
#include <iostream>
using namespace std;


int main()
{
	//错误示例——一个原始指针初始化多个shared_ptr
    int* p = new int(1);
    std::shared_ptr<int> p1(p);
    std::shared_ptr<int> p2(p);			//这样子是错的

    //查看引用计数
    cout << "p1.use_count() = " << p1.use_count() << endl;
    cout << "p2.use_count() = " << p2.use_count() << endl;


    while (1)
    {

    }

	//如果 退出了shared_ptr 的作用域,也会发生一块内存被 删除了两次,程序卒。
}
  • 不要在函数实参中创建shared_ptr

因为C++的函数参数的计算顺序在不同的编译器不同的约定下可能是不一样的,一般是从右到左,但也
可能从左到右,所以,可能的过程是先new int,然后调用g(),如果恰好g()发生异常,而shared_ptr还
没有创建, 则int内存泄漏了,正确的写法应该是先创建智能指针,代码如下:

function(shared_ptr<int>(new int), g()); //有缺陷
shared_ptr<int> p(new int);
function(p, g()); 
  • 函数想返回 shared_ptr 指针时,不能将this指针作为shared_ptr返回出来,因为this指针本质上是一个裸指针,因此,这样可能会导致重复析构。

错误示例:

#include <iostream>
using namespace std;

class A 
{
public:
    shared_ptr<A> GetSelf()
    {
        return shared_ptr<A>(this);
    }

    ~A()
    {
        cout << "Deconstruction A" << endl;
    }
};

int main()
{
    shared_ptr<A> sp1(new A);
    shared_ptr<A> sp2 = sp1->GetSelf();
    return 0;
}

程序输出:
Deconstruction A
Deconstruction A

正确示例:

#include <iostream>
using namespace std;

class A : public std::enable_shared_from_this<A>
{
public:
    shared_ptr<A>GetSelf()
    {
        return shared_from_this(); // 
    }
    ~A()
    {
        cout << "Deconstruction A" << endl;
    }
};

int main()
{
    shared_ptr<A> sp1(new A);
    shared_ptr<A> sp2 = sp1->GetSelf();
    return 0;
}

除此之外还需注意避免循环引用而导致内存泄露

#include <iostream>
using namespace std;

class A;
class B;

class A 
{
public:

    shared_ptr<B>  bPtr;

    ~A()
    {
        cout << "Deconstruction A" << endl;
    }
};

class B 
{
public:

    shared_ptr<A>  aPtr;

    ~B()
    {
        cout << "Deconstruction B" << endl;
    }
};

int main()
{
    {
        std::shared_ptr<A> ap(new A);
        std::shared_ptr<B> bp(new B);

        ap->bPtr = bp;

        bp->aPtr = ap;
    }

    // 循环引用导致ap bp退出了作用域都没有析构
    cout << "main leave " << endl;
 }

unique_ptr

独占共享指针
注意点:

  • 不允许其他智能指针共享其内部指针,不允许将一个unique_ptr 赋值给另外的智能指针
#include <iostream>
using namespace std;


int main()
{
    std::unique_ptr<int> ptr(new int(10));

    std::shared_ptr<int[]> ptr2;

    ptr2 = ptr;     // 错误:不能这样写
}
  • 不允许赋值给其他指针但是可以通过实体店std::move转移到其他的unique_ptr,不过这样它本身就不享有原来指针的使用权了
#include <iostream>
using namespace std;

int main()
{
    std::unique_ptr<int[]> ptr(new int[10]);

    std::shared_ptr<int[]> ptr2;

    ptr[9] = 9;

    ptr2 = std::move(ptr);			//ptr原来的指针的使用权交给ptr2

    if (!ptr )
    {
        cout << "ptr is null" << endl;
    }

    cout << "ptr2[9] = " << ptr2[9] << endl;
}
  • 和 shared_ptr 不一样的是,unique_ptr 需要指定删除器的时候需要在声明的时候指明
#include <iostream>
using namespace std;

int main()
{
    std::unique_ptr<int[]> ptr(new int[10]);

    std::shared_ptr<int[]> ptr2(new int[10]);

    //std::shared_ptr<int> ptr3(new int(1), [](int* p) {delete p; }); // 正确

    //std::unique_ptr<int> ptr4(new int(1), [](int* p) {delete p; }); // 错误

    std::unique_ptr<int, void(*)(int*)> ptr5(new int(1), [](int* p) {delete p; }); // 正确

}

weak_ptr

weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引shared_ptr,weak_ptr只是提供了对管理对象的一个访问手段。该指针设计的目的就是为了解决shared_ptr 相互引用时的死锁问题,因为该指针不会增加指针的引用,它是对对象的一种弱引用和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。

使用注意点:

  • 通过expired 方法判断所观察资源是否已经释放
#include <iostream>
using namespace std;


int main()
{
    std::shared_ptr<int> ptr(new int(10));
    std::weak_ptr<int> ptr2 = ptr;

    if ( !ptr2.expired())
    {
        cout << "ptr2 所监视指针ptr 没有被释放" << endl;
    }
}
  • 通过lock方法获取监视的shared_ptr 指针
#include <iostream>
using namespace std;


int main()
{
    std::shared_ptr<int> ptr(new int(10));
    std::weak_ptr<int> ptr2 = ptr;

    ptr.reset();

    if( ptr2.expired())
    {
        std::cout << "ptr2 所监视指针ptr 被释放" << endl;
    }
 }
  • 在使用weak_ptr是需要调用expired 方法判断指针是否有效,不然有可能对象资源已经被释放
 #include <iostream>
using namespace std;


int main()
{
    std::shared_ptr<int> ptr(new int(10));
    std::weak_ptr<int> ptr2 = ptr;

	//weak_ptr不能直接 *ptr
	//*ptr2 = 1;						//错误
    *ptr2.lock() = 1;

    if( !ptr2.expired())
    {
        std::cout << "ptr2 指向对象的值为: " << *ptr2.lock();
    }
 }

使用智能指针安全吗?

  • 在多线程的使用中,如果多个线程使用同一个shared_ptr的对象时是不安全的。如果在某一个线程中删除了该对象,其他线程访问的时候就会访问到一个被释放的内存而造成程序崩溃
  • 如果每个线程都有一个独立的shared_ptr,共同管理一个同一份数据,不会出现上面的情况,程序不会崩溃。但是如果有其它线程对数据进行修改的话,其指向的数据也是会被修改的

结束啦

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++智能指针 的相关文章

  • C++智能指针

    文章目录 前言shared ptrunique ptrweak ptr使用智能指针安全吗 xff1f 前言 下面简单的概括了 3中智能指针的在使用时候需要注意的一些地方 xff0c 三种智能指针在离开其作用域之后都会被自动释放 xff0c
  • C++ 智能指针 unique_ptr 详解与示例

    unique ptr 是 C 43 43 11 提供的用于防止内存泄漏的智能指针中的一种实现 xff0c 独享被管理对象指针所有权的智能指针 unique ptr对象包装一个原始指针 xff0c 并负责其生命周期 当该对象被销毁时 xff0
  • 智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的一些注意事项

    智能指针 shared ptr unique ptr 作为函数参数或者返回值时的一些注意事项 当智能指针作为函数的参数或者返回值时 xff0c 一直在纠结到底是用智能指针对象本身还是用原始指针 Herb Sutter大师的文章很好的解决了这
  • 面试可能会问六:智能指针

    先看一下百度百科的解释 xff1a 指针指针 当类中有指针成员时 xff0c 一般有两种方式来管理指针成员 xff1a 一是采用值型的方式管理 xff0c 每个类对象都保留一份指针指向的对象的拷贝 xff1b 另一种更优雅的方式是使用智能指
  • stl智能指针和boost智能指针对比

    先说说stl中的智能指针auto ptr xff0c 先说说auto ptr的特点 std auto ptr用来管理单个堆内存对象 xff0c 但是独享所有权 xff0c 且不允许赋值和拷贝 xff08 没有重载operator 61 xf
  • C++智能指针

    参考 xff1a 头文件auto ptr使用示例 unique ptr类模板声明示例 shared ptr模板声明通过辅助类模拟实现 shared ptrshared ptr使用示例 weaked ptrweak ptr 用法weak pt
  • c++11新特性之独占指针unique_ptr

    独占智能指针unique ptr 独占智能指针不允许其他智能指针共享内部的指针 可以通过它的构造函数初始化一个独占智能指针对象 但是不允许通过赋值将一个unique ptr赋值给另一个unique ptr unique ptr不允许复制 但
  • Qt 智能指针详细介绍

    1 Qt智能指针概述 Qt 提供了一套基于父子对象的内存管理机制 所以我们很少需要去手动 delete 但程序中不一定所有类都是QObject的子类 这种情况下仍然需要使用一些智能指针 注意 在 Qt 中使用智能指针时 一定要避免发生多次析
  • 共享型智能指针的实现share_pointer

    智能指针是一个类 它产生的是一个类对象 而不是一个原生的指针对象 但是为了减少类对象与针对对象使用的差异性 所以share ptr类故意重载了两种常见的指针操作符 和 gt 从而share ptr与普通指针使用方式一样 简言之 就是shar
  • Qt 中的智能指针

    Qt 中的智能指针 上一篇博客中介绍了 C 11 标准中的提供的智能指针 在 Qt 中也提供了类似的替代功能 并且比 C 11 标准中提供的功能还要强大 所以如果我们使用 Qt 作为基础库 那么就没有必要使用C 11 的智能指针 Qt 的智
  • std:weak_ptr 用法小结。

    http blog csdn net coolmeme article details 43266319 参考了这篇博客 感谢博主的贡献 感谢博主的翻译 不过他写的太多了 我只是记录一下使用方法 原理就不深究了 需要了解其原理的可以自行去那
  • 【Qt】Qt中智能指针

    文章目录 一 QPointer 二 QSharedPointer 2 1 常用操作函数 1 返回此对象所引用的指针的值 2 清除这个QSharedPointer对象 删除它可能对该指针的引用 如果这是最后一个引用 那么指针本身将被删除 3
  • c++11 智能指针 (std::shared_ptr)(一)

    定义于头文件
  • 内存的智能管理—智能指针

    前言 我们在使用C和C 进行开发的时候 申请堆区内存是必不可少的 但是很多时候 我们经常忘记释放他导致内存泄漏 从而导致程序崩溃 又或者在尚未使用完成的时候释放 从而导致出现野指针 都是非常危险的现象 所以我们在C 11的标准中提出了智能指
  • C++11智能指针之unique_ptr

    1 智能指针概念 智能指针是基于RAII机制实现的类 模板 具有指针的行为 重载了operator 与operator gt 操作符 可以 智能 地销毁其所指对象 C 11中有unique ptr shared ptr与weak ptr等智
  • c++智能指针

    智能指针 智能指针也是模版 在头文件
  • c++智能指针

    C 智能指针详解 本文系转载 原文出处 诚然原博主总结的非常好 我只是加一些自己觉得需要补充的地方 并且在最后给出目前c 11在智能指针这方面的弥补 一 简介 由于 C 语言没有自动内存回收机制 程序员每次 new 出来的内存都要手动 de
  • C++智能指针之unique_ptr(保姆级教学)

    目录 unique ptr 概述 涉及程序 初始化 手动初始化 std make unique函数 C 14 unique ptr常规操作 不支持操作 该指针不支持拷贝和赋值操作 所以不能拷贝到容器里 移动语义std move releas
  • 【C++11智能指针】shared_ptr的初始化、拷贝构造和拷贝赋值、移动构造和移动赋值

    文章目录 1 智能指针概述 2 shared ptr的初始化 2 1 shared ptr和new结合使用 直接初始化 2 2 make shared函数 3 shared ptr的拷贝构造和拷贝赋值 4 shared ptr的移动构造和移
  • C++智能指针作为函数形参和函数返回值的应用场景

    当智能指针作为函数形参时 在调用此函数时 形参代表的智能指针的引用计数将 1 同时退出此函数时 该形参的引用计数将 1 当形参不是智能指针时 调用该函数和退出该函数时 该形参的引用计数不会变化 当函数的内部创建一个智能指针 并需要在函数外使

随机推荐

  • 从第一个人开始报数(从1到3报数),凡报到3的人退出圈子

    有n个人围成一圈 xff0c 顺序排号 从第一个人开始报数 xff08 从1到3报数 xff09 xff0c 凡报到3的人退出圈子 xff0c 问最后留下的是原来第几号的那位 xff08 1 lt 61 n lt 61 1000000 xf
  • Windows10 Xrdp远程桌面连接ubuntu 20.04,一步到位!

    https blog csdn net avinswang article details 93601312 utm medium 61 distribute pc relevant none task blog BlogCommendFr
  • 远程桌面无响应解决方案

    问题1 mstsc链接远程桌面后 发现只有桌面背景 xff08 桌面图标不见了 xff0c 任务栏不见了 xff0c 鼠标无处可点 xff09 问题2 远程桌面卡住了 问题分析 针对于问题1 xff0c 是因为关闭了explorer exe
  • 公用网络切换为专用网络的详细步骤

    win10连接的网络显示为公用网络 xff0c 一般来说公用网络的安全性不高 xff0c 专用网络安全性会比公用网络要高 具体方法如下 1 我的电脑安装的是win10系统 xff0c 网络状态为 xff1a 公用网络 2 把Windows1
  • mysql使用SSL连接配置学习(一)

    参考 xff1a https www jb51 net article 100432 htm https www cnblogs com mysql dba p 7061300 html 一 SSL介绍 SSL xff08 Secure S
  • 富文本回显

    今天遇了富文本的回显问题 xff0c 查了好多网页 xff0c 最后总结回显最简单方法 xff0c 留个纪念 lt c forEach items 61 34 bidNoticeList 34 varStatus 61 34 status
  • 弹出详细信息窗口

    lt DOCTYPE html PUBLIC 34 W3C DTD HTML 4 01 Transitional EN 34 gt lt html gt lt head gt lt meta charset 61 34 GB 2312 34
  • 字符串中特殊字符处理

    public String htmlReplace String str str 61 str replace 34 amp ldquo 34 34 34 str 61 str replace 34 amp rdquo 34 34 34 s
  • Android开发环境配置

    环境为jdk11 43 android studio2021 jdk11的安装 xff1a 参考https blog csdn net qq 22136439 article details 103295019 注意 xff1a 1 jdk
  • java中文字符乱码编码转换大全

    System out println new String myFileName getBytes 34 gbk 34 System out println new String myFileName getBytes 34 utf 8 3
  • java实现打印套打功能

    package test import java awt print import java awt 实现套打 xff0c 把套打的格式当成一张图片 xff0c 将要填入的数据按其在图片在坐标来定位 public class PrintTe
  • oracle中not in的优化

    ORACLE中NOT IN 的替代 http myjcwy iteye com blog 553563 典型的查询方式为 xff1a SELECT TITLE FROM BOOKSHELF WHERE TITLE NOT IN SELECT
  • Visual Stdio 中的error C2001: 常量中有换行符

    error C2001 常量中有换行符 问题 xff1a 使用Visual Stdio xff0c cout中文的时候 xff0c 有的时候可以正常编译并运行 xff0c 但是有的时候会出现error C2001 常量中有换行符 出现err
  • oracle实现每天定时执行一个计划任务

    http www shangxueba com jingyan 1614101 html oracle实现每天定时执行一个计划任务 创建测试表 SQL gt create table a a date 表已创建 创建一个自定义过程 SQL
  • Spring Security配置访问权限在登录页循环并报错302

    事情是这样的 xff0c 在学习Spring Security框架时 xff0c 使用框架默认的登录页面 xff0c 没有任何问题输入正确的账户和密码后都能登录 xff0c 但是将登录页面换为自定义的页面后就无法登录了 如下 xff1a 密
  • .net core基于Oauth2+jwt两种方式实现身份认证(附单点登录)

    引用地址 xff1a net core基于Oauth2 43 jwt两种方式实现身份认证 附单点登录 cslx5zx5的博客 CSDN博客 net core oauth2 基于 net core 3 1微服务架构的SSO单点登录实战 本文所
  • wordpress中文网站代码下载

    wordpress下载中文网站代码 wordpress网站 https cn wordpress org 下载各个中文版本的 xff1a 提示 xff1a 不用用积分去下载了 方法 xff1a 登录网站 xff1a
  • 源码编译装redis

    源码编译装redis 1 下载包 span class token punctuation span root 64 ZZQVM1 span class token punctuation span span class token com
  • I2C协议

    文章目录 一 什么是I2C xff1f 二 物理层与协议层1 物理层 xff08 1 xff09 I2C总线 xff1a xff08 2 xff09 从地址 xff1a xff08 2 xff09 三种传输模式 2 协议层 xff08 1
  • C++智能指针

    文章目录 前言shared ptrunique ptrweak ptr使用智能指针安全吗 xff1f 前言 下面简单的概括了 3中智能指针的在使用时候需要注意的一些地方 xff0c 三种智能指针在离开其作用域之后都会被自动释放 xff0c