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

    一、智能指针类型&智能指针

    1. 标准库提供了两种智能指针类型(来管理动态分配的对象)

    2. 智能指针

      智能指针就是一个变量、一个对象,即智能指针类型的实例化(比如在整型 int 和变量 i 中,智能指针就类似 i)

    3. 智能指针与指针

      智能指针的行为类似常规指针

      区别:智能指针负责自动释放所指向的对象

    4. 两种智能指针的区别

    智能指针类型 特点
    shared_ptr 允许多个指针指向同一个对象
    unique_ptr 该类型指针“独占”所指向的对象

    二、shared_ptr

    1. 形式

    • shared_ptr<T> p;

      解释:创建一个智能指针时,必须提供额外的信息——指针可以指向的类型

    2. 默认初始化

      智能指针中保存着一个空指针

    3. 初始化

    • shared_ptr<T> p = make_shared<T>(args)
    • shared_ptr<int> p1(new int (100))
    • shared_ptr<int> p2(p)

    4. 每个 shared_ptr 都有一个关联的计数器(该计数器由指向同一对象的shared_ptr共享),也称引用计数(记录有多少个 shared_ptr 指向相同的对象)

      引用计数是shared_ptr所指向的对象的,即是相对智能指针所指向的对象而言的

      初始化一个shared_ptr对象后,其关联的计数器为1(也即该shred_ptr对象所指向的对象的引用计数为1)

      当一个shared_ptr对象的计数器变为0时,它就会自动释放自己所管理的对象(即释放内存)

    5. 支持的操作(蓝色部分为shared_ptr和unique_ptr都支持的操作)

    操作 说明

    shared_ptr<T> sp

    unique_ptr<T> up

    空智能指针,可以指向类型为T的对象
    p 将p作为一个条件判断,若p指向一个对象,则为true
    *p 解引用p,获得它指向的对象
    p->mem 等价于(*p).mem
    p.get() 返回一个常规指针,该指针指向p所指的对象

    swap(p, q)

    p.swap(q)

    交换p和q中的指针
    make_shared<T>(args) 返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化该对象
    shared_ptr<T>p(q) p是shared_ptr q的拷贝,q中的指针必须能转化为T*
    p = q p和q都是shared_ptr,所保存的指针必须能相互转换
    p.use_count() 返回与p共享对象的智能指针数量
    p.unique() 若p.use_count()为1,返回 true;否则返回 false

    6. 备注

      在最后一个shared_ptr销毁前内存都不会释放

      计数器递增:用一个shared_ptr初始化另一个shred_ptr、将它当做参数传递给一个函数、作为函数的返回值

      计数器递减:给shared_ptr赋予一个新值、shared_ptr被销毁(例如一个局部的 shared_ptr离开其作用域)

    7. 其他操作

    操作 说明

    T *q = new T

    shared_ptr<T> p(q)

    p管理内置指针q所指向的对象(该对象是new分配的内存)
    shared_ptr<T> p(q, d) q指向的对象不是new分配的内存,p将使用可调用对象d来代替delete
    shared_ptr<T> p(p2, d) p是shared_ptr p2的拷贝,p将使用可调用对象d来代替delete
    shared_ptr<T> p(u) p从unique_ptr u那里接管了对象的所有权,将u置为空

    p.reset()

    p.reset(q)

    p.reset(q, d)

    若p是唯一指向其对象的shared_ptr,reset会释放此对象

    q为内置指针,会令p指向q

    将会调用d而不是delete来释放q

    注:当将一个shared_ptr绑定到一个普通指针时,我们就将内存的管理责任交给了这个shared_ptr;当使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器

    8. 使用示例

    	int *p = new int(2);
        shared_ptr<int> sp = make_shared<int>(1);
        shared_ptr<int> sp2(p);
        shared_ptr<int> sp3(sp);
        cout << sp3.use_count() << endl;
        int *p2 = sp2.get();
        sp2.reset();
        sp3.reset(new int(5));

    三、unique_str

    1. 某个时刻,只能有一个 unique_ptr 指向一个给定对象

      当unique_str被销毁时,它所指向的对象也被销毁

    2. 没有类似make_shared这样返回一个unique_str的函数

      定义一个unique_str时,需要将其绑定到一个new返回的指针上(和shared_ptr一样,初始化unique_str必须采用直接初始化形式)

    3. 不支持普通的拷贝或赋值操作

      一个unique_str拥有它指向的对象(所以不能让其他的unique_str再指向它的对象啊)

    4. 特有操作(与shared_ptr共享的操作参考上面)

    操作 说明

    unique_str<T> u1

    unique_str<T, d> u2

    空unique_str,可以指向类型为T的对象

    u1使用delete来释放它的指针,u2使用一个类型为d的可调用对象来释放它的指针

    unique_str<T, D> u(d) 同上,用类型为D的对象d代替delete
    u = nullptr 释放u指向的对象,将u置为空
    u.release()

    返回指向u指向的对象的指针,将u置为空

    release返回的指针用来:初始化另一个智能指针,或给另一个智能指针赋值

    u.reset()

    u.reset(q)

    释放u指向的对象,将u置为空

    q是内置指针,令u指向q指向的对象,并释放u原先指向的对象

    注:释放对象即释放内存,将u置为空即“u = nullptr”

    5. 向unique_ptr传递删除器

    • 类似shared_ptr,unique_ptr默认情况下用delete释放它指向的对象
    • 与shred_ptr一样,我们可以重载一个unique_ptr中默认的删除器(但unique_ptr管理删除器的方式与shared_ptr不同)

    6. 使用示例

    	int *p = new int(2);
        unique_ptr<int> up;
        unique_ptr<int> up2(p);
        up.reset(up2.release());
        unique_ptr<int> up3(up.release()); 
    

      

    四、weak_ptr

    1. 一种不控制所指向对象生存期的智能指针

      它指向由一个shared_ptr管理的对象

      将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数

      最后一个指向对象的shared_ptr被销毁,对象就会被释放,故weak_ptr指向的对象可能不存在

    2. 创建一个weak_ptr时,要用一个shared_ptr来初始化它

        auto p = make_shared<int>(42);
        weak_ptr<int> wp(p);

    3. 支持的操作

    操作 说明
    weak_ptr<T> w 空weak_ptr,可以指向类型为T的对象
    weak_ptr<T> w(sp) 与shared_ptr sp指向相同对象的weak_ptr,T必须能转换为sp指向的类型
    w = p p可以是一个shared_ptr或一个weak_ptr
    w.reset() 将w置为空
    w.use_count() 与w共享对象的shared_ptr的数量
    w.expired() 若w.use_count()为0,返回true
    w.lock() 如果w.expired()为true,返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr

    4. 不能直接访问对象

      因为对象可能不存在,故必须调用lock,此函数检查weak_ptr指向的对象是否仍存在(如果存在,lock返回一个指向共享对象的shared_ptr)

    5. 使用示例

    	int *p = new int(2);
        shared_ptr<int> sp(new int(3));
        weak_ptr<int> wp(sp);
    	weak_ptr<int> wp2, wp3;
    	wp2 = wp; 
    	wp3 = sp;
    	wp.reset();		//将wp置为空 
    	cout << wp.use_count() << endl;
    	bool bl = wp.expired();
    	shared_ptr<int> sp2 = wp.lock(); 
    

      

  • 相关阅读:
    vim tab 和4个空格
    python 入门
    pyenv 以及 virtualenv
    Redis Cluster 理论知识
    使用Redis SETNX 命令实现分布式锁
    go runtime scheduler
    LeetCode Valid Parentheses
    LeetCode Rotate Image
    leetcode
    HDU 3657 Game(取数 最小割)经典
  • 原文地址:https://www.cnblogs.com/xzxl/p/7735582.html
Copyright © 2011-2022 走看看