1.std::auto_ptr
智能指针本身就是一个对象,要检查其包含的裸指针 是否存在要用对象.get()方法
(1)使用重载过的 “=” 将一个原有auto_ptr对象赋值给新创建的对象,实质上新对象夺取了原有对象的内存管理权,原有对象就悬空了;再调用方法就会崩溃;
(2)要是使用拷贝构造,实际上只有一块内存,这时内存所有者成为了新对象,新对象出了其函数作用域就会自动析构,释放掉这片内存,旧对象使用方法就会报错崩溃
(3).release()方法只是让出了内存的所有权,而不是释放掉了
std::auto_ptr 可用来管理单个对象的对内存,但是,请注意如下几点
(1) 尽量不要使用“operator=”以及拷贝构造。如果使用了,请不要再使用先前对象。
(2) 记住 release() 函数不会释放对象,仅仅归还所有权。
(3) std::auto_ptr 最好不要当成参数传递(因为出了函数作用域,空间就会销毁,实参就成为野指针)。
(4) 由于 std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。
2.shared_ptr
专门用于共享所有权的,由于要共享所有权,其在内部使用了引用计数
多个指针可以指向一个对象,当最后一个指针退出时才会自动释放内存;
通过调用use_count()可以得到引用计数, 据此你能找到shared_ptr的数量,shared_ptr默认调用delete释放关联的资源。如果用户采用一个不一样的析构策略时,他可以自由指定构造这个shared_ptr的策略
void main( )
{
shared_ptr<Test> sptr1( new Test[5],
[ ](Test* p) { delete[ ] p; } );
}
在此场景下,shared_ptr指向一组对象,但是当离开作用域时,
默认的析构函数调用delete释放资源。实际上,我们应该调用delete[]来销毁这个数组。
用户可以通过调用一个函数,例如一个lamda表达式,来指定一个通用的释放步骤。
(1)reset(): 释放关联内存块的所有权,如果是最后一个指向该资源的shared_ptr,就释放这块内存。
(2)unique: 判断是否是唯一指向当前内存的shared_ptr.
当两个不同组的shared_ptr<> 对象指向同一个对象,就会出现错误,尽量避免这种情况 ;
还有:循环引用.A对B有一个shared_ptr, B对A也有一个shared_ptr ,与sptrA和sptrB关联的资源都没有被释放(当B离开其作用域,其引用计数并没有完全释放,值到了1)
3.weak_ptr
为了解决上面循环引用的问题,引入此指针。
weak_ptr可以共享shared_ptr持有的资源。所以可以从一个包含资源的shared_ptr创建weak_ptr。
weak_ptr不支持普通指针包含的*,->操作。它并不包含资源所以也不允许程序员操作资源
从weak_ptr中创建shared_ptr然后再使用它。通过增加强引用计数,当使用时可以确保资源不会被销毁。当引用计数增加时,可以肯定的是从weak_ptr中创建的shared_ptr引用计数至少为1
创建
可以以shared_ptr作为参数构造weak_ptr.从shared_ptr创建一个weak_ptr增加了共享指针的弱引用计数(weak reference),意味着shared_ptr与其它的指针共享着它所拥有的资源。但是当shared_ptr离开作用域时,这个计数不作为是否释放资源的依据。换句话说,就是除非强引用计数变为0,才会释放掉指针指向的资源,在这里,弱引用计数(weak reference)不起作用。
void main( )
{
shared_ptr<Test> sptr( new Test );
weak_ptr<Test> wptr( sptr );
weak_ptr<Test> wptr1 = wptr;
}
此时wptr1有两个弱引用,一个强引用计数。
将一个weak_ptr赋给另一个weak_ptr会增加弱引用计数(weak reference count)。
当shared_ptr离开作用域时,其内的资源释放了,这时候指向该shared_ptr的weak_ptr发生了什么?weak_ptr过期了(expired);
(1)判断weak_ptr是否指向有效资源,有两种方法:
调用use-count()去获取引用计数,该方法只返回强引用计数,并不返回弱引用计数。
调用expired()方法。比调用use_count()方法速度更快。
从weak_ptr调用lock()可以得到shared_ptr或者直接将weak_ptr转型为shared_ptr
void main( )
{
shared_ptr<Test> sptr( new Test );
weak_ptr<Test> wptr( sptr );
shared_ptr<Test> sptr2 = wptr.lock( );
}
4.unique_ptr
遵循着独占语义。在任何时间点,资源只能唯一地被一个unique_ptr占有。当unique_ptr离开作用域,所包含的资源被释放。如果资源被其它资源重写了,之前拥有的资源将被释放。所以它保证了他所关联的资源总是能被释放。
unique_ptr提供了创建数组对象的特殊方法,当指针离开作用域时,调用delete[]代替delete
unique_ptr<int[ ]> uptr( new int[5] );
当把unique_ptr赋给另外一个对象时,资源的所有权就会被转移。
记住unique_ptr不提供复制语义(拷贝赋值和拷贝构造都不可以),只支持移动语义(move semantics).
unique_ptr提供一个release()的方法,释放所有权,但是不释放资源。