C++智能指针原理及简略使用

智能指针

来点现代C++教程:
https://changkun.de/modern-cpp/zh-cn/05-pointers/

https://www.cnblogs.com/wxquare/p/4759020.html

shared_ptr

核心是RAII(资源获取即初始化),实现的核心机制是线程安全的引用技术和临界区保护

shared_ptr的引用计数是线程安全的,但是shared_ptr本身进行修改时不是线程安全的。

std::shared_ptr<int> ptr = std::make_shared<int>(10);
// 如果两个线程同时执行以下代码是不安全的
ptr = std::make_shared<int>(20);

保护方式:

  1. 互斥锁mutex
  2. 原子量std::atomic<std::shared_ptr<T>>
  3. 单线程

注意,只有通过拷贝或者移动语义才能够增加引用计数,重复make不会

    int a = 10;
    //assert(a != 10);
    shared_ptr<int> sptr10 = make_shared<int>(a);
    shared_ptr<int> sptr11 = make_shared<int>(a);
    cout<<sptr10.use_count()<<endl;
    cout<<sptr11.use_count()<<endl;

输出为:
1
1

unique_ptr

release之后原有的指针仍然存在(14标准也有make_unique

unique移动之后原有的unique ptr指针变为0,避免了出现悬垂指针

weak_ptr

  • expired(): 判断是否全部消除,等价于use_count()==0

  • lock(): 返回一个shared ptr,增加引用计数

  • 强引用:增加引用计数

  • 弱引用:不增加引用计数

一个重要的问题是避免shared_ptr循环引用,最典型的例子是
外部两个shared ptr指向两个不同的类,两个不同的类内部有shared ptr指向彼此(parent和child关系)
方法是将类中一个改为weak,外部不变

示例代码:

#include<iostream>
#include<memory>
using namespace std;

class test{
private:
    int i;
public:
    test(int x) {
        cout<<"create"<<endl;
        i = x;
    }
    ~test() {
        cout<<"destroy"<<endl;
    }
    int geti() {
        return i;
    }
};

int main() {

    shared_ptr<test> sptr1 = make_shared<test>(5);
    auto sptr2 = sptr1;

    cout<<sptr1.get()->geti()<<endl;
    cout<<sptr1.use_count()<<endl;
    cout<<sptr2->geti()<<endl;

    test* t = new test(10);
    unique_ptr<test> uptr1(t);
    cout<<uptr1->geti()<<endl;

    cout<<"\n--------------------------------\n";

    auto uptr2 = move(uptr1);
    cout<<uptr2->geti()<<endl;

    cout<<reinterpret_cast<long long>(uptr1.get())<<endl; // 0
    cout<<reinterpret_cast<long long>(uptr2.get())<<endl; // not 0

    uptr2.release();
    cout<<reinterpret_cast<long long>(uptr2.get())<<endl; // 0
    // no automatic release
    // origin pointer still exists
    unique_ptr<test> uptr3(t);
    cout<<uptr3->geti()<<endl;

    unique_ptr<test> uptr4 = make_unique<test>(15);
    cout<<uptr4->geti()<<endl;

    cout<<"\n--------------------------------\n";

    weak_ptr<test> wptr1(sptr1);
    cout<<wptr1.use_count()<<endl; // 2
    cout<<wptr1.expired()<<endl;
    if(!wptr1.expired()) {
        shared_ptr<test> ptrx = wptr1.lock(); // shared
        cout<<wptr1.use_count()<<endl; // 3
        cout<<sptr1.use_count()<<endl; // 3
    }

    return 0;
}

面试实战:***后端开发一面,实现shared_ptr

弱智的点在于我当时实在想不出来引用计数怎么实现,直接static了,最后毫无疑问的挂掉了

联动上一篇:https://www.cnblogs.com/kazusarua/p/18387827

posted @ 2024-12-09 02:00  真昼小天使daisuki  阅读(10)  评论(0编辑  收藏  举报