大概长这个样子
//大概长这个样子(化简版) template<class T> class unique_ptr{ T* ptr; };
unique_ptr是独占性智能指针,
例如:
class Movie { public: Movie(string name) { this->name = name; cout << "let‘s watch moive " << name << endl; } ~Movie() {cout << "movie " << name << " end" << endl;} void getName() {cout<< "name=" << name << endl;} private: string name; }; void test_unique_ptr() { unique_ptr<Movie> p1(new Movie("ne za")); unique_ptr<Movie> p2(new Movie("the lord of the ring")); //unique_ptr<Movie> p3 = p1; // Error! 不支持赋值操作 unique_ptr<Movie> p3 = move(p1); //p1->getName(); // Error! 转移给p3以后,p1不再指向原对象 p3->getName(); }
也可以用release方法来转移对象所有权,例如:
void test_unique_ptr2() { unique_ptr<Movie> p1(new Movie("ne za")); unique_ptr<Movie> p2(new Movie("the lord of the ring")); p2.reset(p1.release()); if (p1 == nullptr) { cout << "p1 is nullptr" << endl; } p2.reset(); if (p2 == nullptr) { cout << "p2 is nullptr" << endl; } }
p1.release() 方法转移其对象控制权(但并不会释放对象),并将p1赋空;
p1.reset(p2) 方法释放p1指向的对象,并重新指向p2所指向的对象;
p1.reset() 方法释放p1指向的对象,并赋空;
shared_ptr 是在使用引用计数的机制上提供了可以共享所有权的智能指针。
大概长这个样子
//大概长这个样子(化简版) struct SharedPtrControlBlock{ int shared_count; }; template<class T> class shared_ptr{ T* ptr; SharedPtrControlBlock* count; };
每次复制,多一个共享同处资源的shared_ptr时,计数+1;每次释放shared_ptr时,计数-1。
当shared计数为0时,则证明所有指向同一处资源的shared_ptr们全都释放了,则随即释放该资源(哦,还会释放new出来的SharedPtrControlBlock)。
初始化方式如下:
shared_ptr<T> ptr(new T(), deleter); // deleter 是自定义释放器,可以不传
auto ptr = std::make_shared<T>()
一个例子:
void test_shared_ptr() { shared_ptr<Movie> p1(new Movie("ne za")); // count = 1 do {shared_ptr<Movie> p2 = p1;} while(0); // count先加后减 shared_ptr<Movie> p3 = p1; // count = 2 p1.reset(); // count = 1 //p3 = nullptr; // count = 0 cout << "test_shared_ptr " << endl; }
如果把上面p3=nullptr这行的注释去掉,则会在这里导致计数器变0,从而引发对象的释放。
shared_ptr类提供的成员方法:
循环引用的情况:
class Movie { public: Movie(string name) { this->name = name; cout << "let‘s watch moive " << name << endl; } ~Movie() {cout << "movie " << name << " end" << endl;} void getName() {cout<< "name=" << name << endl;} void setRelative(shared_ptr<Movie>& other) { relative_movie = other; } private: string name; shared_ptr<Movie> relative_movie; }; void test_shared_ptr2() { shared_ptr<Movie> p1(new Movie("ne za")); shared_ptr<Movie> p2(new Movie("the lord of the ring")); p1->setRelative(p2); p2->setRelative(p1); cout<<p1.use_count()<<endl; // 2 cout<<p2.use_count()<<endl; // 2 }
上面的 test_shared_ptr2 函数执行完毕后,两个Movie对象析构函数都没有打印,也就是没有被释放。
模拟下代码流程:
为了解决这个问题,引入了weak_ptr指针。
weak_ptr是一种不控制所指向对象生命周期的智能指针,它指向一个shared_ptr管理的对象。
大概长这个样子:
struct SharedPtrControlBlock{ int shared_count; int weak_count; }; template<class T> class weak_ptr{ T* ptr; SharedPtrControlBlock* count; };
特点
class Movie { public: Movie(string name) { this->name = name; cout << "let‘s watch moive " << name << endl; } ~Movie() {cout << "movie " << name << " end" << endl;} void getName() {cout<< "name=" << name << endl;} void setRelative(shared_ptr<Movie>& other) { relative_movie = other; } private: string name; weak_ptr<Movie> relative_movie; }; void test_weak_ptr() { shared_ptr<Movie> p1(new Movie("ne za")); shared_ptr<Movie> p2(new Movie("the lord of the ring")); p1->setRelative(p2); p2->setRelative(p1); cout<<p1.use_count()<<endl; // 1 cout<<p2.use_count()<<endl; // 1 }
这个例子,两个对象都能够被释放;
同样也模拟下代码流程:
另外,weak指针没有重载 * 和 -> ,所以并不能直接使用资源,但可以对weak指针调用lock方法,会返回一个shared_ptr指针。
void test_weak_ptr2() { shared_ptr<Movie> p1(new Movie("ne za")); weak_ptr<Movie> p2 = p1; //p2->getName(); // Erorr! shared_ptr<Movie> p3 = p2.lock(); p3->getName(); }
原文:https://www.cnblogs.com/chenny7/p/8946704.html