概述
在多线程环境下,当一个对象能被多个线程同时看到时,而程序员需要自己管理对象生命期时,对象的析构时机就会模糊不清,而智能指针可以帮助解决这类问题,想要了解智能指针就先要了解RAII
RAII即资源获取即初始化。简单来讲就是使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,最后在对象析构的时候,释放构造时获取的资源。它可以用来管理资源、避免资源泄漏。智能指针就是RAII的一种应用
智能指针主要讲三种:shared_ptr、unique_ptr、weak_ptr
shared_ptr
它控制对象的生命期,多个指针可以指向相同的对象,内部维护一个引用计数,当引用计数为0时,自动释放资源
#include <iostream>
#include <memory>
using namespace std;
struct A {
int n;
A(int a=0):n(a){}
~A() { cout << n << "destructor" << endl; }
};
int main() {
shared_ptr<A> sp1(new A(3));//sp1指向A(3)
shared_ptr<A> sp2(sp1);//sp2指向A(3)
cout <<"1)" <<sp1->n << "," << sp2->n << endl;
A* p = sp1.get();//获取指针对象
cout << "2)" << p->n << endl;
shared_ptr<A> sp3;
sp3 = sp1;//sp3指向A(3)
cout << "3)" << (*sp3).n << endl;
sp1.reset();//重置sp1
if (!sp1)
cout << "4)sp1 is null" << endl;
A* q = new A(4);
sp1.reset(q);//重置sp1指向A(4)
cout << "5)" << sp1->n << endl;
sp1.reset();
return 0;
}
结果
成员函数获取 this 指针的 shared_ptr 的正确的做法是继承 enable_shared_from_this,调用
shared_from_this函数
#include <iostream>
#include <memory>
using namespace std;
class A :public enable_shared_from_this<A>{
public:
int n;
A(int a = 0) :n(a) {}
~A() { cout << n << "destructor" << endl; }
shared_ptr<A> getstr() { return shared_from_this(); }
};
int main() {
shared_ptr<A> sp1(new A(3));//sp1指向A(3)
cout << sp1->n << endl;
auto sp2 = sp1->getstr();
cout << sp2->n << endl;
cout << sp2.use_count() << endl;//打印引用计数
return 0;
}
结果
weak_ptr
weak_ptr 一般与 shared_ptr 一起使用。 weak_ptr 可以看做是 shared_ptr 管理对象的观察者,它不影响对象的生命周期。可以将 weak_ptr 提升为 shared_ptr。当 shared_ptr 管理的对象被释放时,weak_ptr 会自动变成 nullptr。
#include <iostream>
#include <memory>
using namespace std;
struct A {
int n;
A(int a=0):n(a){}
~A() { cout << n << "destructor" << endl; }
};
int main() {
weak_ptr<A> wp;
{
shared_ptr<A> sp1(new A(3));//sp1指向A(3)
wp = sp1;
if (auto tmp = wp.lock())//判断是否可以提升为shared_ptr
cout << tmp->n << endl;
else
cout << "lock fail" << endl;
}
if (auto tmp = wp.lock())
cout << tmp->n << endl;
else
cout << "lock fail" << endl;
return 0;
}
结果
unique_ptr
它控制对象的生命期,且一个unique_ptr只能指向一个单独的对象
#include <iostream>
#include <memory>
using namespace std;
struct A {
int n;
A(int a=0):n(a){}
~A() { cout << n << "destructor" << endl; }
};
int main() {
unique_ptr<A> up(new A(3));//up1指向A(3)
cout << up->n << endl;
//unique_ptr<A> up1 = up;//编译错误,不能传值
//unique_ptr<A> up1(up);//上同
unique_ptr<A> up1 = move(up);//正确
//cout << up->n << endl;//错误
cout << up1->n << endl;
A* a=up1.release();//释放管理的对象
cout << a->n << endl;
if (up1)
cout << up1->n << endl;
else
cout << "NULL" << endl;
unique_ptr<A> up2(a);
return 0;
}
结果