C++的智能指针
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏
为什么要用智能指针
如果申请的空间在函数结束时忘记释放,则会造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针是一个类,当超出了类的实例对象的作用域时,会自动调用对象的析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间
auro_ptr
auro_ptr 是C++98中的智能指针方案,采用所有权模式,但在C++11中被弃用
auto_ptr<string> p1 (new string ("hello world"));
auto_ptr<string> p2;
p2 = p1;
p2剥夺了p1的所有权,程序访问p2时不会报错,但是访问p1时程序会报错,auto_ptr仍存在内存泄漏的问题。
unique_ptr
(替换auto_ptr)unique_ptr 用于不能被多个实例共享(独占)的内存管理。就是说仅有一个实例拥有内存所有权,保证同一时间内只有一个智能指针指向一个对象,对于避免内存泄露非常有效
unique_ptr<string> p1 (new string ("hello world"));
unique_ptr<string> p2;
p2 = p1; // 编译时将会报错
当把一个unique_ptr赋值给另一个时,如果unique_ptr是一个临时右值,将会被允许操作
unique_ptr<string> p;
p = unique_ptr<string>(new string("hello world")); // 编译通过
这里调用unique_ptr的构造函数,当将构造函数创建的临时变量的所有权转让给p
之后就会销毁
- unique_ptr相比起auro_ptr更加的安全
标准库STL
提供了一种方法std::move()
可以将一个unique_ptr赋值给另一个,也就是转移所有权,使用这个语法时你应该明白是在干什么,而不是在胡乱使用指针
shared_ptr
shared_ptr 实现共享式概念。多个智能指针可以指向相同的对象,这个对象和其相关的资源会在最后一个引用被释放的时候才会释放。
shared_ptr 使用计数机制来实现指针的共享,可以通过use_count()
方法来查看指针个数。
除了使用 new
构造之外,还可以通过传入,auto_ptr、unique_ptr、weak_ptr 来构造,当调用release()
方法时,当前指针会释放资源所有权,计数值减一,当计数值为零时,则释放资源。
shared_ptr 中的一些方法
方法 | 描述 |
---|---|
use_count() | 返回引用计数的个数 |
unique() | 返回是否独占所有权,即计数为1 |
swap() | 交换所拥有的对象 |
get() | 返回内部对象(指针) |
reset() | 放弃内部对象的所有权或者拥有对象的变更,会引起原有对象的引用技术减少 |
shared_ptr相比于auto_ptr已经解决了很多的问题,但是当两个shared_ptr互相指向对方(循环引用),指针计数个数不会降为零,资源将一直不会被释放,导致内存泄漏,为了解决这个问题,又引入了 weak_ptr
weak_ptr
weak_ptr是指向一个shared_ptr管理的对象
weak_ptr最初设计的目的是用来辅助shared_ptr工作,属于对对象的弱引用,构造时不会增加引用计数
weak_ptr和shared_ptr之间可以互相转化
- shared_ptr可以直接赋值给它
- weak_ptr可以调用lock函数来获得shared_ptr
方法 | 描述 |
---|---|
expired () | 检测所管理的对象是否已经释放,已经释放返回true 否则返回false |
lock() | 获取所管理的对象的shared_ptr ,如果expired() 为true ,则返回一个空的shared_ptr |
use_count() | 返回shared_ptr 共享的对象的引用计数 |
reset() | 放弃内部对象的所有权或者拥有对象的变更,会引起原有对象的引用技术减少 |