一般来说,C++中一共有4种智能指针,包括引入于C++98的auto_ptr,以及引入于C++11的unique_ptr/shared_ptr/weak_ptr
auto_ptr:源自于C++98的老大哥
信息 |
说明 |
引入于 |
C++98 |
定义于 |
<memory> |
优点 |
当指针对象被销毁时,它所管理的对象也会自动被delete掉 |
缺点 |
让我们在下面慢慢说 |
创建方法 |
auto_ptr ap(new string(“this is an auto_ptr”)); |
支持 |
拷贝构造,有参构造,无参构造 |
开始慢慢说吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include<iostream> #include<memory> #include<vector> using namespace std;
int main() { string *p=new String("This is a auto_ptr"); auto_ptr<string> p1(p); auto_ptr<string> p2(p); auto_ptr<string> p3(p); auto_ptr<string> p4(p3); cout<<*p3; int pp[10]={0}; auto_ptr<int> p5(pp); vector<int> pi; vector.push_back(1); vector.push_back(2); vector.push_back(3); auto_ptr<vector<int>> p6=&pi[0]; }
|
unique_ptr:auto_ptr的优秀继承者
信息 |
说明 |
引入于 |
C++11 |
定义于 |
<memory> |
优点 |
相对于auto_ptr来说,更加安全 |
创建方法 |
unique_ptr ap(new string(“this is an unique_ptr”)); |
支持 |
有参构造,无参构造,拷贝构造 |
在auto_ptr中,虽然也有所有权的定义,但如果使用有参构造,,同一个对象仍然可以由多个不同的auto_ptr共享,因此也就造成了同一片内存空间可能被多次释放/释放后调用,调用空指针等UB类问题
但对在unique_ptr中,加强了所有权,一个对象只可以由一个unique_ptr进行独享,所有权可以被释放,可以被转移,但绝不能被共享,因此弥补了auto_ptr的一些缺陷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include<iostream> #include<memory> #include<vector> using namespace std;
int main() { unique_ptr<string> up1; up1.reset(new string("This is an unique_ptr")); unique_ptr<string> up2(new string("unique_ptr2")); unique_ptr<string> up3; string *p=up1.release(); up3=move(up2); up4.reset(up3.release()); up2.reset(); up4=nullptr;
unique_ptr get(){ unique_ptr<int> temp(new int(3)); return temp; } unique_ptr<int> gotit=get();
}
|
shared_ptr:允许多个指针指向同一个对象
信息 |
说明 |
引入于 |
C++11 |
定义于 |
C++11后:<memory> C++11前:Boost库 |
优点 |
相对于unique_ptr来说,允许多指针指向同一对象,且安全 |
创建方法 |
shared_ptr sp(new string(“this is an unique_ptr”)); |
支持 |
有参构造,无参构造,拷贝构造 |
在shared_ptr中,引入了”计数器”这一概念,当多个指针指向同一个对象时,这些指针共享同一个计数器,记录着改对象被引用的次数,当指针被销毁时,计数器会同步减少,当计数器减少到0时,该对象会被自动销毁
但是注意,shared_ptr在指针是线程不安全的,因此在涉及到修改等操作时需要加锁(mutex)
weak_ptr:和shared_ptr通力合作的亲密友指针(其实也不能说是个智能指针)
信息 |
说明 |
引入于 |
C++11 |
定义于 |
C++11后:<memory> C++11前:Boost库 |
优点 |
相对于unique_ptr来说,允许多指针指向同一对象,且安全 |
创建方法 |
shared_ptr sp(new string(“this is an unique_ptr”)); |
支持 |
无参构造,有参构造,拷贝构造 |
特性 |
可以弱引用shared_ptr且不会增加计数器计数 |
该指针被设计成和shared_ptr共同使用,可以用于观测shared_ptr目前的状态或对shared_ptr指向的对象进行一些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include<iostream> #include<memory> #include<vector> using namespace std;
int main() { shared_ptr<string> sp1(new string("This is an unique_ptr")); weak_ptr<string> wp(up1); cout<<wp.use_count(); cout<<wp.expired(); string *p=wp.lock(); }
|
那么这个指针的意义是什么?难道只是一个观星者吗?
答案:解除循环依赖问题
假设我们现在有两个对象A和B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class A{ public: void setpb(B* b){ pb.reset(b); } private: shared_ptr<B> pb;
} class B{ public: void setpb(A* a){ pb.reset(a); } private: shared_ptr<A> pa; }
|
在我们实例化A类和B类,并调用两个set方法注入A和B的成员指针后,A和B构成了循环依赖,这两个类会因为该依赖关系而都无法被自动销毁(永远都会因为对方的成员指针而导致计数器不为0),此时我们可以调用weak_ptr获取实例之后进行手动销毁
注意:通过weak_ptr的成员函数lock()获取的是其引用的shared_ptr所指向的对象,并不是副本或拷贝