【C++】智能指针的简单介绍

tech2026-09-23  1

智能指针

智能指针是包含重载运算符的类,其行为像常规指针,但智能指针能够及时、妥善的销毁动态分配的数据,并实现了明确的对象生命周期,因此更有价值

unique_ptr

#include<memory>

std::unique_ptr 是通过指针占有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象的智能指针。

在下列两者之一发生时用关联的删除器释放对象:

销毁了管理的 unique_ptr 对象通过 operator= 或 reset() 赋值另一指针给管理的 unique_ptr 对象。

简而言之,一个对象只能由一个unqiue_ptr指向控制 当此指针没了 则所指向的对象立马销毁

#include<iostream> #include<memory> using namespace std; struct A{ public: A() : a(0){} A(int a) : a(a){cout << "A constructor : " << this << endl;} ~A() {cout << "A desconstructor : " << this << endl;} private: int a; }; int main(){ //unique_ptr<A> p(new A(5)), q = p;//报错 unique_ptr指向的对象只能由一个unique_ptr指向 //unique_ptr对象不能复制!! //shared_ptr<A> p(new A(5)), q = p;//不会报错 unique_ptr<A> p(new A(5)), q(new A(6)); //指向对象的unique_ptr被销毁或者转移指向目标则该对象销毁 //p = nullptr; p = move(q); cout << "end of main()" << endl; return 0; } A a; unique_ptr<A> p(&a); //这样样在析构时会报错 //先析构智能指针对象 则对象a也会被析构 //再析构对象a时 段错误

shared_ptr

#include<memory>

std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象。下列情况之一出现时销毁对象并解分配其内存:

最后剩下的占有对象的 shared_ptr 被销毁;最后剩下的占有对象的 shared_ptr 被通过 operator= 或 reset() 赋值为另一指针。

简而言之,一个对象可以被多个shared_ptr指向控制 当这些指向同一个对象的智能指针没了 则所指向的对象立马销毁

自己实现一个简单的shared_ptr:

#include<iostream> using namespace std; namespace haizei{ template<typename T> class shared_ptr{ public: shared_ptr() : ptr(nullptr), pcnt(nullptr){} shared_ptr(T *ptr) : ptr(ptr), pcnt(new int(1)){} shared_ptr(const shared_ptr<T> &p) : ptr(p.ptr), pcnt(p.pcnt){ *pcnt += 1; } shared_ptr<T> &operator=(shared_ptr<T> &p){ this->use_count_des();//p = q 说明p原本指向的对象的计数器需要-1 q指向指向的对象的计数器需要+1 this->ptr = p.ptr; this->pcnt = p.pcnt; *pcnt += 1; return *this; } int use_count(){ return (pcnt ? *pcnt : 0); } T *operator->(){return this->ptr;} T &operator*() {return *(this->ptr);} ~shared_ptr(){ use_count_des(); } private: void use_count_des(){ if(pcnt){ *pcnt -= 1; if(*pcnt == 0){ delete pcnt; delete ptr; } } } T *ptr; int *pcnt; //地址 所有的指向同一个对象的智能指针计数器在同一个位置 }; class A{ public: int x, y; A() : x(123), y(456){ cout << "A constr : " << this << endl; } ~A(){ cout << "A desconstr : " << this << endl; } haizei::shared_ptr<A> p; }; }; int main(){ //haizei::A a; haizei::shared_ptr<haizei::A> p(new haizei::A()), q = p; haizei::shared_ptr<haizei::A> k(new haizei::A()); cout << p->x << " " << p->y << endl; cout << q->x << " " << q->y << endl; cout << p.use_count() << endl;//2 p和q指向同一个对象1 k单独2 q = k; cout << p.use_count() << endl;//1 k和q指向同一个对象2 p单独1 //p = k;//第一个对象A被析构 //cout << p.use_count() << endl;//3 pqk指向同一个对象2 /* p->p = k; k->p = p;//环形引用 两个对象没有被析构 想析构1必须先析构2 想析构2必须先析构1 //为了解决环形引用引入weak_ptr 和 unique_ptr */ return 0; }

weak_ptr

std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(“弱”)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。

std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。std::weak_ptr 的另一用法是打断 std::shared_ptr 所管理的对象组成的环状引用。若这种环被孤立(例如无指向环中的外部共享指针),则 shared_ptr 引用计数无法抵达零,而内存被泄露。能令环中的指针之一为弱指针以避免此情况。 #include<iostream> #include<string> #include<memory> using namespace std; class A{ public: string name; A(const string &theName) : name(theName){} }; int main(){ auto x = make_shared<A>("A"); cout << x->name << endl; { auto y = x; cout << y->name << endl; } weak_ptr<A> w = x; //将作用域去掉下面输出w不为空 因为临时的y为shared_ptr形式一直存在 对象一直没被释放掉 //如果有作用域符号 下面输出w为空 临时的y shared_ptr已经被释放 x = nullptr说明没有shared_ptr指向这个对象 对象就被释放掉了 { auto y = w.lock(); cout << y->name << endl; } x = nullptr; { auto y = w.lock(); if(y) cout << "w不为空" << endl; else cout << "w为空" << endl; } return 0; }
最新回复(0)