一直对智能指针一知半解,面试的时候也含含糊糊。现在整理一下每种指针及其原理。
智能指针原理
智能指针就类通过出作用域自动析构函数来实现的
简单实现代码:
// 定义资源类
class student{
public:
student(){
cout<<"创建了一个student对象"<<endl;
}
~student(){
cout<<"销毁了一个student对象"<<endl;
}
void test(){
cout<<"student test"<<endl;
}
};
// 手写智能指针类
// 1、能够通过出作用域来实现对象的自动释放
// 2、能够用起来像一个指针
class smartptr{
public:
smartptr(student* s){
s1 = s;
}
~smartptr(){
if(s1 != nullptr){
delete s1;
}
}
student* operator->(){
return s1;
}
student& operator*(){
return *s1;
}
private:
student *s1;
};
auto_ptr 与 unique_ptr
unique_ptr
指针持有对象的独有权即两个unique_ptr 不能指向一个对象。
无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL)算法。只能移动 unique_ptr,即对资源管理权限可以实现转移。
使用方法:
unique_ptr<int> u_i;
u_i.reset(new int(3)); // reset 重新指定
unique_ptr<int> u_i2(new int(4));
unique_ptr<int> u_i3(new int(5));
//u_i = u_i2; // 不能直接赋值
//unique_ptr<int> u_i4(u_i); // 当然也不能拷贝构造
int *p = u_i2.release(); // release释放所有权
// u_i.reset(u_i3.release()); // 与移动语句等价
u_i = move(u_i3);
cout<<*u_i.get()<<endl;
auto_ptr的缺点
安全性方面
unique_ptr不能直接赋值(浅拷贝),auto_ptr可以直接赋值但这中复制也是释放资源。
unique_ptr能避免因潜在的内存问题导致程序崩溃。
auto_ptr<int> a_i(new int(1));
auto_ptr<int> a_i2 = a_i;
功能方面
auto_ptr不可放在容器中,unique_ptr可以
//放到容器中
vector<unique_ptr<int>> v {};
vector<auto_ptr<int>> v1 ;
// 管理数组对象,unique_ptr 默认的资源删除操作是 delete/delete[]
// auto_ptr<int[]> p(new int[3]{1,2,3});
unique_ptr<int []> u(new int[3]{1,2,3}) ;
shared_ptr
原理与特点
- 允许多个指针指向同一对象,利用引用计数实现
weak_ptr
循环引用解释
class CSon;
class Cperson{
public:
Cperson(){
}
void Set(shared_ptr<CSon> p_son){
m_pson = p_son;
}
~Cperson(){
}
shared_ptr<CSon> m_pson;
};
class CSon{
public:
CSon(){
}
~CSon(){
}
void Set(shared_ptr<Cperson> parent){
m_parent = parent;
}
shared_ptr<Cperson> m_parent;
};
// 两个对象相互引用对方
shared_ptr<Cperson> shared_parent(new Cperson());
shared_ptr<CSon> shared_son(new CSon());
shared_parent->Set(shared_son);
shared_son->Set(shared_parent);
// 两个指针的引用计数都为2,退出作用域都会减为1,无法自动释放资源
弱智针使用
shared_ptr<int> q_1(new int(3));
shared_ptr<int> q_2 = q_1;
weak_ptr<int> w_1 = q_1;
// 判断是否有强指针关联
if(!w_1.expired()){
shared_ptr<int> s_1 = w_1.lock();
cout<<s_1.use_count();
}
为什么会存在强弱指针的计数?
弱指针不影响强指针的引用计数。
弱指针不可直接使用,需要调用lock()提升。
上面循环引用的问题可以通过将成员变量变为弱引用指针来解决。