c++ 智能指针

智能指针

  • 智能指针式为了解决手动管理动态分配内存的问题,使用RAII(资源获取即初始化)原则,通过在对象的构造函数中分配内存,并在对象的析构函数中释放内存,从而保证资源的正确释放,避免了内存泄漏

std::unique_ptr

  • 管理独占所有权的对象指针,保证在其周期结束时释放内存,智能通过移动语义来转移所有权,不能进行复制,通常用于单个所有者的场景,比如管理动态分配的对象或者资源
std::unique_ptr<int> ptr(new int(42));
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
  • 这个就是将裸指针进行一个单纯的封装,构造函数和析构函数

std::shared_ptr

  • 允许多个指针共享同一个对象,使用引用计数来追踪有多少个指针指向相同的对象,只有当最后一个std::shared_ptr超出作用域时,内存才会被释放,通常用于共享资源所有权的场景
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1;
  • shared_ptr需要维护的信息有两部分
    • 指向共享资源的指针
    • 引用计数等共享资源的控制信息——事实上是维护一个指向控制信息的指针
std::shared_ptr<T> sptr1(new T);

image

std::shared_ptr<T> sptr2 = sptr1;

image

  • 这里看着每个shared_ptr对象和控制信息都指向共享资源,但是有的时候不会指向同一个,但是这里不会指向同一个的情况暂时没看懂

std::weak_ptr

  • 是对std::shared_ptr的一种扩展,允许观察共享对象但不拥有它,不会增加引用计数,因此不会影响对象的声明周期,但是不能访问所观察的对象
  • 主要是和shared_ptr共同使用,但不会增加和减少shared_ptr的引用计数,主要用来获得对应shared_ptr的状态信息
std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
std::weak_ptr<int> weakPtr = sharedPtr;

image

  • 当shared_ptr析构并释放共享资源的时候,只要weak_ptr对象还存在,控制块就会保留,weak_ptr可以通过控制块观察对象是否存活
    image

循环引用问题

  • 智能指针循环引用指的是在使用智能指针时,存在多个智能指针相互引用,形成一个循环的情况,会导致资源无法被正确释放,从而导致内存泄漏
class A;
class B;

class A {
public:
    std::shared_ptr<B> bPtr;
    ~A() {
        std::cout << "A destructor called." << std::endl;
    }
};

class B {
public:
    std::shared_ptr<A> aPtr;
    ~B() {
        std::cout << "B destructor called." << std::endl;
    }
};

int main() {
    std::shared_ptr<A> pa = std::make_shared<A>();
    std::shared_ptr<B> pb = std::make_shared<B>();
    pa->bPtr = pb;
    pb->aPtr = pa;

    return 0;
}

  • 此时两个Object的引用计数都是2,例如A的两个引用是pa,pb->ptrA,这里不能说A的两个引用,但是是表示这个意思
  • 此时线程结束,pa,pb结束,但是引用计数只是变为了1,此时ptrA,ptrB没有被释放。
  • 可以将shared_ptr换成weak_ptr,因为weak_ptr不增加引用计数
  • 上述程序什么也不会输出,因为A B还存在引用计数,因此不会调用对应的析构函数
posted @ 2023-06-13 10:25  白菜茄子  阅读(12)  评论(0编辑  收藏  举报