std::shared_ptr和std::weak_ptr学习记录

std::shard_ptr是智能指针,通过引用计数的方式共享对象的所有权,在引用计数为0时自动释放对象占用的内存。

int main(){
       int *p = new int(10);
       std::shared_ptr<int> a(p, [](int* p) {std::cout << "[deleter called]\n"; delete p;});
       std::cout << "p=" << p <<" a.get()=" << a.get() << " a=" << a << '\n';
       std::shared_ptr<int> b(a);
       std::cout << "b.use_count(): " << b.use_count() << '\n';
       std::cout << "b=" << b <<" b.get()=" << b.get() << " a=" << a << '\n';
       return 0;
}

运行信息:

p=0x798c20 a.get()=0x798c20 a=0x798c20

b.use_count(): 2

b=0x798c20 b.get()=0x798c20 a=0x798c20

通过打印信息,可以看出:p, a.get(), a, b, b.get()的值是一样的,是同一指针。

Note1:shared_ptr对象只能通过复制它们的值来共享所有权如果两个shared_ptr是从同一个(shared_ptr)指针构造(或生成)的,它们都将拥有该指针,但不共享它,当其中一个释放该指针(删除其管理对象),而让另一个指向无效位置时,会导致潜在的访问问题。即上面的例子中,应该通过std::shared_ptr<int> b(a)定义对象b,这样引用计数会增加;而不应该通过std::shared_ptr<int> b(p)来定义对象b

Note2: 循环引用导致的内存泄露问题。

#include <iostream>
#include <memory>

using namespace std;

class Abase;
class base {
public:
    base(string name): mName(name) {
        cout << "construct " << mName << endl;
    }

    virtual ~base() {
        cout << "deconstruct " << mName << endl;
    }

    void print() {
        cout << mName << " will print" << endl;
    }

public:
    string mName;
    shared_ptr<Abase> base_ptr;
};



class Abase {
public:
    Abase(string name):mName(name){
        cout << "construct " << mName << endl;
    }

    virtual ~Abase() {
        cout << "deconstruct " << mName << endl;
    }

    void print() {
        cout << mName << " will print" << endl;
    }

public:
    string mName;
    shared_ptr<base> Abase_ptr;
};



int main(int argc, char* argv[]) {
    {

        shared_ptr<Abase> A(new Abase("AAAAAAA"));
        shared_ptr<base> B(new base("BBBBBBB"));
        cout << B.use_count() << endl;
        cout << A.use_count() << endl;
        A->Abase_ptr = B;
        B->base_ptr = A;
        cout << B.use_count() << endl;
        cout << A.use_count() << endl;
    }

    return 0;

}

日志输出:

construct AAAAAAA

construct BBBBBBB

1

1

2

2

weak_ptr可以与shared_ptr对象共享指针,而不需要拥有它们,即不会增加引用计数从而解决了shared_ptr循环引用导致的内存泄露问题。上面的例子只要将Abasebase中的指针类型改成weak_ptr即可走到各自的析构函数中。

shared_ptr中的reset()函数:释放shared_ptr对象共同拥有的对象的所有权,即共享所有权的引用计数减一。

weak_ptr中的lock和expired函数比较重要,因为它本身不会增加引用计数,所以它指向的对象可能在它用的时候已经被释放了,所以在用之前需要使用expired函数来检测是否过期,如果expired() == true(函数expired()的功能等价于use_count()==0),表示实际对象已经不复存在了,这个时候调用lock返回的是一个指向null的shared_ptr对象;如果expired() == false,可以使用lock函数来获取其对应的shared_ptr对象(lock()会创建shared_ptr指针,在该指针的作用域范围内,会使引用次数+1,出作用域,引用次数-1)。

参考:

shared_ptr和weak_ptr的区别与联系_haodada1226的博客-CSDN博客_shared_ptr weak_ptr

shared_ptr和weak_ptr_csdn_cjc的博客-CSDN博客_shared_ptr weak_ptr

weak_ptr - C++ Reference

shared_ptr - C++ Reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值