zoukankan      html  css  js  c++  java
  • 智能指针

    有三个智能指针,auto_ptr(弃用)、unique_ptr、shared_ptr.
    智能指针可以自动跟踪动态内存,在其过期时自动释放。

    #include<memory>
    

    一、shared_ptr

    用于new创建的对象,而不适用于new[]创建的对象,
    用于多个指针共享一个地址的情况。
    默认初始化的智能指针中保存着一个空指针。

    1.1 make_shared函数

    最安全的分配和使用动态内存的方法是调用make_shared函数;
    通常使用auto定义一个对象来保存make_shared的结果,
    注意,auto只能用来初始化单个值,因此不能用来初始化列表。

    auto p=make_shared<int>(42);//p指向的对象只有p一个引用者
    auto q(p);//p和q指向相同的对象,此对象有两个使用者。
    

    不能将一个内置指针隐式转化为一个智能指针:

    shared_ptr<int>p1=new int(1024);//错误,必须使用直接初始化方式
    shared_ptr<int>p2(new int(1024));//正确,使用了直接初始化方式
    

    1.2 智能指针不能使用动态生存期资源的类:

    1. 程序不知道自己需要使用多少对象;
    2. 程序不知道所需对象的准确类型;
    3. 程序需要在多个对象之间共享数据。

    1.3 智能指针使用规范

    1. 不使用相同的内置指针值初始化(或reset)多个智能指针;
    2. 不delete get()返回的指针;
    3. 不使用get()初始化或reset另一个智能指针;
    4. 如果你使用get返回的指针,记住当最后一个对应的指针销毁后,你的指针就变为无效了;
    5. 如果你使用智能指针管理的资源不是new分配的内存,记住传递给他一个删除器。

    二、unique_ptr

    用于只存留一个指针指向最后地址的情况,同时unique_ptr有指向new[]的版本。
    控制权转移。

    unique_ptr必须使用直接初始化方式:

    unique_ptr<double> p1;
    unique_ptr<int> p2(new int(42));
    

    unique_ptr的“独占”是指:不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr。例如:

    std::unique_ptr<int> p (new int);
    std::unique_ptr<int> q = p; //error
    

    但是unique_ptr允许通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,注意,这时它本身就不再拥有原来指针的所有权了。

    std::unique_ptr<int> p (new int);
    std::unique_ptr<int> q = std::move(p); //ok
    

    三、操作

    3.1 shared_ptr和unique_ptr都支持的操作

    操作 作用
    shred_ptrsp,unique_ptrup 空智能指针,可以指向类型为T的对象
    p->mem 等价于(*p).mem
    p.get() 返回p中保存的指针
    swap(p,q),p.swap(q) 交换p和q中的指针

    3.2 shared_ptr中独有的操作

    操作 作用
    make_shared(args) 初始化一个智能指针
    shared_ptrp(q) 使用q初始化p,会增加计数
    p=q q必须能转化为shared_ptr类型
    p.uniqe() 判断计数是否为1,是1返回true
    p.use_count() 返回与p共享对象的智能指针数量

    3.3 unique_ptr中独有的操作

    操作 作用
    unique_ptr(T) u1 , unique_ptr(T,D)u2 空智能指针,u1使用delete释放指针,u2使用D释放指针
    unique_ptr(T,D)u(d) 空指针,使用类型为D的对象d代替delete
    u=nullptr 释放u指向的对象,将u置为空
    u.release() 释放u的控制权,将u置为空
    u.reset() 释放u指向的对象
    u.reset(q),u.reset(nullptr) 如果提供了内置指针q,令u指向这个对象;否则将u置为空

    四、weak_ptr

    弱指针用于避免share_ptr循环引用的问题。
    由于弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。
    虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题。

    五、动态数组

    大多数情况下使用动态数组都是使用vector来实现。
    标准库提供了一个可以管理new分配的数组的unique_ptr版本。

    unique_ptr<int[10]>up(new int [10]);//初始化
    up.release();//自动用delete[]销毁其指针
    

    5.1 allocator类

    TODO:)

    其他

    如ps是一个智能指针对象,则可以对它:

    解除引用*ps
    访问结构成员ps->index
    将它赋给同类型常规指针

    unique_ptr为右值时,可将其赋给shared_ptr
    unique_ptr赋给另一个unique_ptr时,需要使用移动构造函数std::move()

    参考链接:
    https://www.cnblogs.com/wuyepeng/p/9741241.html
    https://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html

  • 相关阅读:
    C#几个经常犯错误汇总
    vs2010密钥
    SQL数据库基础知识用sql语句创建数据库
    空值显示表格线条(border)
    vs2008常用快捷方式
    汉字与十六进制之间的相互转换
    asp.net中常用信息验证总结
    GridView中全选和反选
    Nonreentrant C# timer
    GC.Collect
  • 原文地址:https://www.cnblogs.com/chendeqiang/p/12861555.html
Copyright © 2011-2022 走看看